
1.一篇就夠了(建議收藏)——超詳解sizeof與strlen的用法
2.C語言之深入指針進階(建議收藏以備不時之需)
3.回爐重造的C之指針+結構體
【C語言】大廠指針筆試題詳解(1碼+1圖)——程式結果判斷題
筆試題1
筆試題2
筆試題3
筆試題4
筆試題5
筆試題6(重點難題)
代碼分析:
①
int a[4] = { 1, 2, 3, 4 };
由于本人電腦是小端(将低位位元組存儲在起始位址)存儲,是以數組在記憶體中的儲存如圖
②
int *ptr1 = (int *)(&a + 1);
&a+1
的類型是
int(*)[4]
,強制轉化成
int*
類型,賦給
int*
型指針變量
ptr1
③
int *ptr2 = (int *)((int)a + 1);
如圖所示,将00位置的位址賦給了
int*
ptr2
④
printf( "%x,%x", ptr1[-1], *ptr2);
因為
ptr1[-1
]等價于
*(ptr1-1)
,
ptr1
又是
int*
類型的指針,大小為4位元組,-1往回跳過4個位元組
是以按16進制輸出
ptr1[-1]
就是 4
指針
ptr2
裡存的是
00
這個位置的位址,又因為這個位址是
int*
類型的,大小為4位元組
是以
*ptr2
之後結果為0x02 00 00 00,按16進制列印出來是2000000
① int a[3][2] = { (0, 1), (2, 3), (4, 5) };
這句代碼有個坑,就是二維數組裡是小括号,小括号裡的是逗号表達式(逗号表達式的取值是最後一個元素的值,計算後的最終值是一個元素),是以這裡初始化二維數組時
(0,1)結果是1
(2,3)結果是3
(4,5)結果是5
最終存入二維數組的隻有1,3,5 結果如圖
② int *p;
定義一個指針變量p
③ p = a[0];
a[0]是第一行數組的數組名,單獨放在這裡表示的就是是第一行首元素的位址,将第一行首元素的位址賦給指針變量p
④ printf( "%d", p[0]);
p是個指針,p[0]等價于*(p+0)等價于*(a[0]+0)等價于*a[0],是以這裡列印的其實是第一行第一列的元素1,結果如下
int a[5][5];
初始化一個5×5的二維數組,在記憶體中是這樣存放的
② int(*p)[4];
聲明一個指向4個整型元素的數組指針
③ p = a;
a單獨使用表示的是二維數組首元素位址,也就是第一行a[0]的位址,把這個位址指派給數組指針p
④ printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
逐個分析
如圖&a[4][2],取a[4][2]的位址
如下圖
&p[4][2]
注意:指針減去指針,結果是指針之間元素的個數
分别按将變量值以位址形式即16進制形式 和整型列印結果 -4,-4的原反補碼如下
列印結果如圖所示
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
&aa
是取整個二維數組的位址,+1跳過整個數組之後,再強制類型轉化成
int*
類型,并指派給指針變量
ptr1
如圖
③ int *ptr2 = (int *)(*(aa + 1));
aa單獨放,表示二維數組第一行的位址,因為指針類型是int(*)[5],+1之後其實就是第二行的位址,再将其解引用,得到的是第二行數組名,數組名單獨放在這又表示數組首元素位址,将這個首元素位址強制轉換成int*類型,指派給ptr2
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
ptr1和ptr2的指針類型都是int*, -1後 , 表示的是上一個位址,如圖
列印結果為
代碼分析
char *a[] = {"work","at","alibaba"};
定義一個
char*
類型的指針數組,包含三個字元串
char**pa = a;
a
單獨使用表示的是數組首元素位址,将首元素位址指派給一個二級指針
pa
pa++;
printf("%s\n", *pa);
*pa
(pa已經自增過一次)得到的是字元串“
at\0
”的位址,是以通過
%s
列印字元串
結果是
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
前三行代碼可以畫圖表示為
printf("%s\n", **++cpp);
cpp
前置++,相當于
c+2
的位址,
*++cpp
表示
c+2
**++cpp
表示得到字元串“POINT\0”的位址,%s列印出來就是POINT
⑤
printf("%s\n", *--*++cpp+3);
這時候需要注意,cpp已經+1過了,現在指向的是c+2
現在看這行代碼的符号操作順序,方框由内向外的順序
一步一步看:
①++cpp,指向c+1
②*++cpp,解引用得到c+1這個空間 裡存放的位址
③--* ++cpp,c+1裡的位址本來指向的是字元串NEW\0的位址,現在- -之後,位址實際上指向的是字元串ENTER\0的位址
④*--*++cpp+3 表示的就是對指向ENTER\0位址的位址(c+1- -)解引用,得到ENTER\0的位址,+3,就是字元E的位址,最終就是從E開始列印字元,%s列印得到結果ER
⑥ printf("%s\n", *cpp[-2]+3);
cpp[-2]等價于*(cpp-2),整體表達式替換成**(cpp-2)+3
由于cpp經過上邊語句的變化,現在指向的是c+1,-2之後指向的應該是c+3,兩次解引用之後得到的是FIRST\0的位址,再+3,得到的就是字元S的位址,%s列印結果為ST
⑦ printf("%s\n", cpp[-1][-1]+1);
cpp[-1][-1]可以替換成*(*(cpp-1)-1)+1
cpp現在指向的c+1,-1之後指向c+2,解引用得到c+2裡的位址,裡邊位址原本指向POINT\0的位址,現在再-1,變成指向NEW\0的位址,再對這個位址解引用得到NEW\0的位址,+1之後,表示的就是字元E的位址,%s列印結果是EW
完整運作結果如下