指標學完之后,對指標是否深刻理解,以下是一些關于指標的經典例題,通過例題可以回顧一下指標的相關內容:
代碼示例1:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));//2,5
return 0;
}
代碼詳解1:
首先,&a表示的是整個陣列的地址,其型別是int*[5],(&a+1)表示跳過整個陣列的地址,(int *)(&a + 1),強制型別轉換為(int*)型別,int *ptr = (int *)(&a + 1);
就可用下圖來表示:

對于(ptr-1)的位置上進行解參考即*(ptr - 1), 就可得到最后的結果為:5
同樣,a表示的是首元素的地址,(a+1)表示指向第2個元素的地址,*(a+1)表示對(a+1)進行解參考,最后得到的結果為2,
代碼示例2:
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假設p 的值為0x100000, 如下表運算式的值分別為多少?
//已知,結構體Test型別的變數大小是20個位元組
int main()
{
p = (struct Test*)0x100000;
printf("%p\n", p + 0x1);//0x100014
printf("%p\n", (unsigned long)p + 0x1);//0x100001
printf("%p\n", (unsigned int*)p + 0x1);//0x100004
return 0;
}
代碼詳解2:
重點考察:指標+1.
上面的例子中p是一個結構體指標型別,則p的型別是struct Test*,0x100000是十六進制,為一個整形型別,要將0x100000強制型別轉換為struct Test*型別,
- 1
p + 0x1:結構體指標+1,實際上是加了一個1 x 結構體的大小,結構體Test型別的變數大小是20個位元組,即結構體指標+1x20-->0x100000+1x20,此處為十六進制(0x)的表示形式所以要將20轉化為十六進制即14,(4 x 16^0 + 1 x 16^1),所以最后所的結果為0x100014, - 2
(unsigned long)p + 0x1):強制型別轉換為整形,即(unsigned long)p + 0x1)就是加了一個整形1,所得結果為:0x100001,
- 3
(unsigned int*)p + 0x1):強制型別轉換為整形指標,整形指標+1,即跳過一個整形的大小(4),則最后所的結果為:0x100004,
代碼示例3:
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);// 4,2000000
return 0;
}
代碼詳解3:
VS2013為小端存盤模式:即低位存盤在低地址處,高位存盤在高地址處,
&a表示的是整個陣列的地址,(&a+1)表示跳過整個陣列的地址,(int *)(&a + 1),強制型別轉換為(int*)型別,則ptr指向的位置可用下圖表示:
ptr1[-1]-->*(ptr+(-1))-->*(ptr-1),由于其是小端存盤模式,則它解參考之后的輸出順序應該為:00 00 00 04,所以ptr1[-1]最后的輸出結果為:4

a表示首元素的地址,(int)a表示強制轉換成 int型,((int)a+1)表示地址值加1,就是向后偏移一個地址,則ptr2指向的位置就如上圖所示,對ptr2解參考就是從ptr2向后數4個地址即為一個整形的地址(上圖藍圈圈出的地方),然后進行輸出,即為02 00 00 00-->2000000,
代碼示例4:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]); //1
return 0;
}
代碼詳解4:
重點:**逗號運算式表示的結果實際上取決于逗號運算式里面最后一個值表示的結果,**即(0,1)-->(1),(2,3)-->(3),(4,5)-->(5),所以a陣列里面放的值實際上為{1,3,5};陣列里面的其他位置就放的是0,放置效果如下圖所示:

a[0]表示第一行的陣列名,這里即沒有出現&a[0],也沒有sizeof(a),所以a[0]就表示陣列的首元素地址,p[0]-->*(p+0)-->*p:即指向的元素為1,
代碼示例5:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//FFFFFFC,-4
return 0;
}
代碼詳解5:
a[5][5]是一個5行5列的陣列,其可用下圖形式表示,第一行到第五行的陣列名可用a[0]---a[4]表示,&a[4][2]很容易就可以從陣列中找出,如上圖所指處,int(*p)[4] :p是一個指標,指向的是一個陣列,陣列里面有4個元素,陣列的型別為int型別,p+1跳過4個整形元素,則p+4就是跳過16個整形元素,如上圖所畫處,
p[4][4]-->*(*(p+4)+2),&p[4][2] - &a[4][2]小的減去大的,兩者之間相差4個元素,則得到的是-4,
10000000 00000000 00000000 00000100 //-4原碼
11111111 11111111 11111111 11111011 //反碼
11111111 11111111 11111111 11111100 //補碼 (在記憶體中的存貯方式)
以%d的形式列印,列印出的為原碼(-4),
以%p的形式列印,即以地址的形式列印就沒有原碼,反碼,補碼的概念,則它會直接以補碼的形式列印出來,即:F F F F F F F C,
代碼示例6:
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1)); //10,5
return 0;
}
代碼詳解6:

&aa取出的是整個二維陣列的地址,(&aa + 1)跳過整個二維陣列,(int *)(&aa + 1)強制轉換為int*型別,將其賦值給ptr1,ptr1-1向前移動一個位元組,然后對其進行解參考后指向的元素就為10,
aa是個陣列名,表示的是第一行的地址,aa+1代表第2行的地址,對其進行解參考,相當于拿到了第2行(得到了第2行的陣列名),(*(aa + 1))-->a[1],則ptr2指向的位置如上圖所示,就可輕易推斷出*(ptr2 - 1)的結果,
代碼示例7:
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa); //at
return 0;
}
代碼詳解7:

char *a[]指標陣列,a表示首元素的地址,a里面的每個型別都是char*型別,將a賦給pa,pa里面的每個型別都是char**型別,pa指向的是首元素的地址,pa++,向后移動一個單位位元組,對其進行解參考得到最終結果:at,
代碼示例8:
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
代碼詳解8:
char *c[]指標陣列,c表示首元素的地址,c里面的每個型別都是char*型別,
cp中共有4個元素,每個元素都是char**型別,則它對應于陣列c中得位置如下圖綠色箭頭所指處,將cp賦值給cpp,其為char***型別,
cpp為一個指標,它指向的是cp中第一個元素的位置,++cpp向下移動一個元素(指向c+2位置),*(++cpp)對其進行解參考,找到了cp陣列中c+2位置的元素,**++cpp再對其進行解參考,找到了陣列c中對應位置的元素,即為POIN,如下圖綠線所描述路徑,
++cpp再向下移動一個元素(指向c+1位置),*++cpp解參考的到c+1里面的元素,c+1 對用的是c中的第二個元素, --*++cpp:cpp里面的元素減1,即變為c,對應陣列 c 中得第一個元素, *--*++cpp:對其進行解參考,拿到陣列c中對應位置的元素,*--*++cpp+3:從元素所指位置向后移動3個元素位置,最終所的結果為:ER,如下圖棕線所描述路徑,
*cpp[-2]-->*(cpp-2):由c 所指的位置向上移動2個位置,即指向(c+3)所在位置,其對應的是陣列c中得第4個元素的位置,*cpp[-2]+3:從元素所指位置向后移動4個元素位置,最終所的結果為:ST,
cpp[-1][-1]+1可寫為*(*cpp-1)-1)+1,cpp-1:向下移動一個位置,指向(c+2)所在位置,其對應的是陣列c中得第3個元素的位置,(*cpp-1)-1):表示從陣列c中對應位置向上移動一個元素位置,其對應的是陣列c中得第2個元素的位置,*(*cpp-1)-1)+1:對陣列c中得第2個位置處進行解參考,并從元素所指位置向后移動1個元素位置,輸出為字串形式,則最終所的結果為:EW,


以上,如有不足之處,還望指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/299670.html
標籤:其他
上一篇:資料結構之雙向帶頭回圈鏈表
下一篇:【資料結構】鏈表經典演算法題集錦
