首先,來看代碼:
[html]
view plaincopyprint?
- <SPAN style="FONT-SIZE: 18px">#include <stdio.h>
- void main()
- {
- char a[] = "BruceLee!";
- char *p = a;
- printf("%c\n", *(p+4));
- printf("%c\n", p[4]);
- printf("%s\n", p);
- printf("%c\n", a[4]);
- printf("%c\n", *(a+4));
- printf("%s\n", a);
- }</SPAN>
#include <stdio.h>void main(){char a[] = "BruceLee!";char *p = a;printf("%c\n", *(p+4));printf("%c\n", p[4]);printf("%s\n", p);printf("%c\n", a[4]);printf("%c\n", *(a+4));printf("%s\n", a);}
首先程式聲明了字元數組a,並且初始化,這個記得是預設後面加'\0'的。然後聲明了字元指標,指向數組a的首地址,也是a[0]的地址,這裡
[html]
view plaincopyprint?
- char *p = a; 等價於char *p = &a[0]
char *p = a; 等價於char *p = &a[0]
。*(p+4) = p[4] = a[4] = *(a+4),這是最終的結果。這裡需要注意的是,字元指標p和數組的名字a每個都有兩種引用方法,一種是數組的引用方法如a[4],一種是*(a+4),指標的方法。
注意這裡的
[html]
view plaincopyprint?
- <SPAN style="FONT-SIZE: 18px">printf("%s\n", p);列印的內容仍然是<SPAN style="FONT-SIZE: 18px"></SPAN></SPAN><PRE class=html name="code">BruceLee!</PRE><PRE class=html name="code"></PRE>
printf("%s\n", p);列印的內容仍然是[html] view plaincopyprint?
- BruceLee!
BruceLee!
[html]
view plaincopyprint?
-
也就是說我們僅僅是通過*(p+4),來查看裡面的內容,但並沒有改變p的指向。p仍然指的是首地址,所以列印出的字串也是從首字元開始的。
如果我們再代碼中,加上這兩句:
printf("%c\n", *p++);
printf("%s\n", p);
第一句執行結果是列印首字元‘B’,然後p往後移一位。所以下面一句列印字串,直接從第二個字元開始的,結果是ruceLee。
總結:(*p+4)這種方式並未改變指標p的指向。只有p++、p--或者p+=4類似這種方式,才改變指標p的指向!
下面再來看一個例子:
[cpp]
view plaincopyprint?
- <SPAN style="FONT-SIZE: 18px">#include <stdio.h>
- void main()
- {
- int a[5] = {1, 2 ,3 , 4, 5};
- int *p = a;
- printf("%d\n", a[0]);
- printf("%d\n", *p);
- printf("%d\n", p);
- int *q = (int *)a;
- printf("%d\n", q[0]);
-
- }</SPAN>
#include <stdio.h>void main(){ int a[5] = {1, 2 ,3 , 4, 5}; int *p = a; printf("%d\n", a[0]); printf("%d\n", *p); printf("%d\n", p); int *q = (int *)a; printf("%d\n", q[0]); }需要說的有兩點:
1,
[cpp]
view plaincopyprint?
- <SPAN style="FONT-SIZE: 18px">printf("%d\n", p);</SPAN>
printf("%d\n", p);這句話是不能正常執行的,列印出來和數組a毫無相關的數字。不要期望像printf(“%s”, p)p為首地址。這種方式企圖列印整個數組a的內容!
2,int *p = a; 和 int *q = (int *)a,這兩句話效果是一樣的,在這裡加不加前面的強制轉換都一樣。
再看這個迷惑性強的例子:
[cpp]
view plaincopyprint?
- #include <stdio.h>
- void main()
- {
- int a[5] = {1, 2 ,3 , 4, 5};
- int *m = (int *)&a[0];
- printf("%d\n", *(m + 1));
- int *p = (int *)&a;
- printf("%d\n", *(p + 1));
- int *q = (int *)(&a + 1);
- printf("%d\n", *(q-1));
- int *w = (int *)(&a[0] + 1);
- printf("%d\n", *(w-1));
-
-
- }
#include <stdio.h>void main(){ int a[5] = {1, 2 ,3 , 4, 5}; int *m = (int *)&a[0]; printf("%d\n", *(m + 1)); int *p = (int *)&a; printf("%d\n", *(p + 1)); int *q = (int *)(&a + 1); printf("%d\n", *(q-1)); int *w = (int *)(&a[0] + 1); printf("%d\n", *(w-1)); }有三個要點:
1,注意上面我們說那麼(int *)可有可無,但是當加了&後,在int *m = (int *)&a[0]這裡,如果不加強制轉換會警示,因為這裡取了地址,最好強制轉換一下!
2,(int*)(&a[0]) 和(int *)(&a),從列印m和p的值來看,貌似這兩種操作是沒有區別的,但其實並非如此!&a[0] = a,都是代表數組a的首地址,也就是a[0]的地址。但&a是整個對象,也就是a這個數組整體的首地址。緊跟其後的指標q的申明,&a + 1究竟是誰的地址呢?
我們要切記,對指標進行加1操作,得到是下一個元素的地址,而不是原有地址的數值直接加1,這點大家肯定都知道。假設類型為x,則加1後,指標向後移動sizeof(x),移動是以sizeof(x)為單位的!
我怎麼越說越不明白了,其實就是a和&a[0]以及&a,三者的區別!
前兩個是等價的。&a上面也說過了,把a看成一個整體,所以&a + 1是a下一個對象的地址,即&a + 1,以相對a或者&a[0]來說,移動了sizeof(a) = 5*4 = 20個位元組,即這裡指標q指向a[5]!所以*(q - 1)的值是5,也就是a[4] 的值。 為了對照區別,最後我取了(&a[0] +
1)來做對照,w在申明時指向a【1】,*(q-1)的值是1,也就是a[0]的值。
3,int *n = a 等價於 int *n = (int *)&a[0] ,從指向上來看也等價於 int *n = (int *)&a;
但 當有指標加減操作時,兩者的結果絕不相同!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
如:int *n = (int *)(&a[0] + 1)絕不等於 int *n = (int *)(&a + 1)。
http://blog.csdn.net/yanzi1225627/article/details/7858231