【本文鏈接】
http://www.cnblogs.com/hellogiser/p/pointer-summary.html
1.指針注意事項
(1). 指針類型字符串不容許修改
char *str1=”abcd”; char str2[]=”abcd”;的區別。指針類型的字符串一般不允許修改,如:str1[0]=’c’;這樣的語句會導致運行時錯誤。
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void test_string()
{
char *str1 = "abcd";
char str2[] = "1234";
cout << str1 << endl; // abcd
cout << str2 << endl; // 1234
cout << *str1 << endl; // a
cout << *str2 << endl; // 1
//str1[0]='X'; // ERROR
str2[0] = 'Y'; // right
cout << *str2 << endl; // Y
}
(2).指針/數組作為參數進行傳遞
在C語言中,參數是使用值傳遞的。 int func(int a );當調用者調用該函數的時候將傳遞一個值給a,這個a只是你傳遞進去的參數的一個副本。而數組傳遞的時候,會退化為指針,其將數組的首地址復制給形參。看下面的一個例子。
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
void fun(char str[])
{
printf("After transform:%d\n", sizeof(str)); //4
}
int main()
{
char strs[] = "abcdefg";
printf("Before transform:%d\n", sizeof(strs)); //8
fun(strs);
return 0;
}
(3). 在函數內部修改指針本身(無效)vs修改指針指向的內容(OK)
許多初學C指針的同學想在函數內部修改作為參數傳遞進來的指針的值。看以下代碼:
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef struct Link_Node
{
int Elem;
struct Link_Node *next;
} LinkNode, *PLinkList;
void CreateList(LinkNode *header)
{
int i = 0;
header = (LinkNode *)malloc(sizeof(LinkNode));
header->Elem = 10;
header->next = NULL;
}
int main()
{
LinkNode *head = NULL;
CreateList(head);
if(head != NULL)
printf("%d\n", head->Elem);
free(head);
return 0;
}
/*
A: head---0
---CreateList---
B: header---0
C: NODE
B: header---C
---CreateList---
A: head---0
*/
此做法無效,在函數內部修改header的地址,函數結束後回到main函數,head仍然是null。
我們可以修改其指向的變量的值,而不能修改指針本身的內容了。為了能夠修改指針本身的內容,我們需要傳遞指針本身的地址。所以在上面那例中,需要傳遞head指針本身的地址。代碼如下:
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef struct Link_Node
{
int Elem;
struct Link_Node *next;
} LinkNode, *PLinkList;
void CreateList(LinkNode **header)
{
int i = 0;
(*header) = (LinkNode *)malloc(sizeof(LinkNode));
(*header)->Elem = 10;
(*header)->next = NULL;
}
int main()
{
LinkNode *head = NULL;
CreateList(&head);
if(head != NULL)
printf("%d\n", head->Elem);
free(head);
return 0;
}
/*
A: head---0
---CreateList---
B: header---A
C: NODE
A: head---C
B: header---A
---CreateList---
A: head---C
*/
下面我們再看一例,在函數內部修改指針指向的內容。
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
#include "stdafx.h"
#include <iostream>
using namespace std;
void Trans(int *Arr, int nLength)
{
for(int i = 0; i < nLength; i++)
{
// modify content of *pointer
Arr[i] += i + 20;
}
}
int main()
{
int nArr[5] = {0};
int i;
printf("Before:\n");
for(i = 0; i < 5; i++)
printf("%d ", nArr[i]);
//0 0 0 0 0
Trans(nArr, 5);
printf("\nAfter\n");
for(i = 0; i < 5; i++)
printf("%d ", nArr[i]);
// 20 21 22 23 24
return 0;
}
http://blog.csdn.net/gamecreating/article/details/5382711
http://www.cnblogs.com/nezha/p/3204410.html
2. 指針vs數組
數組名不是變量!指針是變量!
數組名僅僅是一個符號,不是變量,它沒有自己的存儲空間,而指針是個變量,有自己的空間。
C標准有一條:當數組出現在函數的參數中時,無論是形參還是實參,都轉換為指針再進行操作。
http://blog.jobbole.com/44863/
3. 指針的指針
http://blog.jobbole.com/60647/
4. 數組指針vs指針數組
http://blog.csdn.net/touch_2011/article/details/6966980
http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html
簡單舉例說明:
int *p[2]; 首先聲明了一個數組,數組的元素是int型的指針。
int (*p)[2]; 聲明了一個指針, 指向了一個有兩個int元素的數組。(數組指針,也稱行指針)
其實這兩種寫法主要是因為運算符的優先級, 因為[]的優先級比*高。所以第一種寫法,p先和[]結合,所以是一個數組,後與*結合,是指針。後一種寫法同理。
指針數組如下處理就會很清楚: typedef int* intPtr; intPtr p[2]; 一目了然,所以為了避免迷惑,做適當的typedef也是很有必要的。
同理,數組指針也可以作類似處理: typedef int intArray2[2]; intArray2 * p; 和原來的聲明都是等價的。
數組指針(也稱行指針)
定義 int (*p)[n];
()優先級高,首先說明p是一個指針,指向一個整型的一維數組,這個一維數組的長度是n,也可以說是p的步長。也就是說執行p+1時,p要跨過n個整型數據的長度。
如要將二維數組賦給一指針,應這樣賦值:
int a[3][4];
int (*p)[4]; //該語句是定義一個數組指針,指向含4個元素的一維數組。
p=a; //將該二維數組的首地址賦給p,也就是a[0]或&a[0][0]
p++; //該語句執行過後,也就是p=p+1;p跨過行a[0][]指向了行a[1][]
所以數組指針也稱指向一維數組的指針,亦稱行指針。
指針數組
定義 int *p[n];
[]優先級高,先與p結合成為一個數組,再由int*說明這是一個整型指針數組,它有n個指針類型的數組元素。這裡執行p+1是錯誤的,這樣賦值也是錯誤的:p=a;因為p是個不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它們分別是指針變量可以用來存放變量地址。但可以這樣 *p=a; 這裡*p表示指針數組第一個元素的值,a的首地址的值。
如要將二維數組賦給一指針數組:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
這裡int *p[3] 表示一個一維數組內存放著三個指針變量,分別是p[0]、p[1]、p[2]
所以要分別賦值。
這樣兩者的區別就豁然開朗了,數組指針只是一個指針變量,似乎是C語言裡專門用來指向二維數組的,它占有內存中一個指針的存儲空間。指針數組是多個指針變量,以數組形式存在內存當中,占有多個指針的存儲空間。
還需要說明的一點就是,同時用來指向二維數組時,其引用和用數組名引用都是一樣的。
比如要表示數組中i行j列一個元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
優先級:()>[]>*
sizeof分析
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
int _tmain(int argc, _TCHAR *argv[])
{
// array pointer
int a[2][3] = {1, 2, 3, 4, 5, 6};
int (*p)[3];
p = a;
// test sizeof
// for a
cout << sizeof(a) << endl; // 24
cout << sizeof(a + 0) << endl; // 4 (24 in debug local watch)
cout << sizeof(a + 1) << endl; // 4 (24 in debug local watch)
cout << sizeof(a[0]) << endl; // 12
cout << sizeof(a[1]) << endl; // 12
cout << sizeof(*(a + 0)) << endl; // 12
cout << sizeof(*(a + 1)) << endl; // 12
cout << sizeof(a[0][0]) << endl; // 4
// for p
cout << sizeof(p) << endl; // 4
cout << sizeof(p + 0) << endl; // 4
cout << sizeof(p + 1) << endl; // 4
cout << sizeof(p[0]) << endl; // 12
cout << sizeof(p[1]) << endl; // 12
cout << sizeof(*(p + 0)) << endl; // 12
cout << sizeof(*(p + 1)) << endl; // 12
cout << sizeof(p[0][0]) << endl; // 4
return 0;
}
5. 函數指針
http://www.cnblogs.com/nezha/p/3204410.html
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/6/3
*/
typedef int (*func)(char a[], int nLength);
int total(char a[], int nLength)
{
int nTotal = 0;
for(int i = 0; i < nLength; ++i)
nTotal += a[i];
return nTotal;
}
int main()
{
char a[] = "abcde";
int nLength = strlen(a);
func fp;
fp = total;
printf("%d\n", fp(a, nLength));
return 0;
}
【本文鏈接】
http://www.cnblogs.com/hellogiser/p/pointer-summary.html