
c語(yǔ)言指針例題
28頁(yè)1、程序運(yùn)行的結(jié)果是什么呢?int main(){ int a[5] = { 1, 2, 3, 4, 5 }; int* ptr = (int*)(&a + 1); printf("%d,%d", *(a + 1), *(ptr - 1)); return 0;}解析:*(a + 1) - 解釋:就不再過多解釋ptr - 1) - 解釋·: &a表示取整個(gè)數(shù)組的地址,對(duì)其加一跳過整個(gè)數(shù)組,指針指向了紅色箭頭指向的位置,但是這個(gè)指針又被強(qiáng)制類型轉(zhuǎn)換成了整形(int*)類型的指針,并存放在ptr這個(gè)整形指針變量里面去了此時(shí)的ptr指針就是一個(gè)整形指針,對(duì)其減一就是向前跳動(dòng)一個(gè)整形的地址指向了藍(lán)色箭頭的位置,*(ptr - 1)是以整形指針的視角去讀取所指空間的內(nèi)容,也就是從藍(lán)色箭頭的指針處向后訪問一個(gè)整形(4個(gè)字節(jié))的長(zhǎng)度,所以讀到的就是52、程序運(yùn)行的結(jié)果是什么呢?備注://p是結(jié)構(gòu)體指針//假設(shè)p 的值為0x100000 如下表表達(dá)式的值分別為多少?//已知,結(jié)構(gòu)體Test類型的變量大小是20個(gè)字節(jié)struct Test{ int Num; char* pcName; short sDate; char cha[2]; short sBa[4];}*p; int main(){ p = (struct Test*)0x100000; printf("%p\n", p + 0x1); printf("%p\n", (unsigned long)p + 0x1); printf("%p\n", (unsigned int*)p + 0x1); return 0;}解析:計(jì)算機(jī)內(nèi)存十一字節(jié)劃分的,一個(gè)字節(jié)都有一個(gè)對(duì)應(yīng)的地址,地址是由16進(jìn)制來表示的。
printf("%p\n", p + 0x1); - 解釋:p = (struct Test*)0x100000;是將0x100000 強(qiáng)制類型轉(zhuǎn)換成(struct Test*)這個(gè)結(jié)構(gòu)體的地址而我們知道指針的類型決定了指針加減整數(shù)的時(shí)候跳過的字節(jié)數(shù);如:int*類型的指針 + 1 跳過4個(gè)字節(jié), char* 類型的指針 + 1跳過1個(gè)字節(jié), 所以結(jié)構(gòu)體類型的指針 + 1 就跳過一個(gè)結(jié)構(gòu)體因?yàn)檫@個(gè)結(jié)構(gòu)體的大小為20個(gè)字節(jié),+1之后指針就向后跳20個(gè)字節(jié),20的16進(jìn)制是14 所以結(jié)果就為00100014printf("%p\n", (unsigned long)p + 0x1); - 解釋:(unsigned long)p 是將這個(gè)結(jié)構(gòu)體的地址強(qiáng)制類型轉(zhuǎn)換成無符號(hào)整形整形數(shù)字 + 1就是+1,所以結(jié)果是00100001printf("%p\n", (unsigned int*)p + 0x1); - 解釋:(unsigned int*)p 是將p強(qiáng)制類型轉(zhuǎn)換成整形指針,整形指針+1就是跳過四個(gè)字節(jié),所以結(jié)果是001000043、程序運(yùn)行的結(jié)果是什么呢?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); return 0;}解析:注意:本題的輸出方式為十六進(jìn)制輸出。
ptr1[-1] - 解釋:與筆試1類似,不再贅述ptr2 - 解釋: a是數(shù)組首元素的地址,是十六進(jìn)制的,強(qiáng)制類型轉(zhuǎn)換成整形(int)之后再 + 1 再?gòu)?qiáng)轉(zhuǎn)成整形指針,也就是在上幾部操作后,a的地址數(shù)值加了1,地址加1 就是向后偏移了一個(gè)字節(jié)在VS的環(huán)境下:存儲(chǔ)方式為小端存儲(chǔ)ptr從 01 指向了后一個(gè)字節(jié) 00int*)((int)a + 1) 再將其強(qiáng)轉(zhuǎn)成整形指針,再向后訪問四個(gè)字節(jié)并以十六進(jìn)制的方式輸出,所以結(jié)果是:2 00 00 00以什么形式存儲(chǔ),就以什么形式輸出,以小端存儲(chǔ)方式存入,就以小端的方式輸出4、程序運(yùn)行的結(jié)果是什么呢?int main(){ int a[3][2] = { (0, 1), (2, 3), (4, 5) }; int* p; p = a[0]; printf("%d", p[0]); return 0;}解析:這道題很簡(jiǎn)單,逗號(hào)表達(dá)式是從左到右一次執(zhí)行,并以最后一個(gè)值作為整個(gè)表達(dá)式的值所以,數(shù)組內(nèi)部布局為: 1 3 5 0 0 0所以p[0]就為第一個(gè)元素15、程序運(yùn)行的結(jié)果是什么呢?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]); return 0;}解析:p是一個(gè)數(shù)組指針,p能夠指向的數(shù)組是4個(gè)元素a 為二維數(shù)組的數(shù)組名,二維數(shù)組的數(shù)組名表示二維數(shù)組第一行的地址。
同時(shí)二維數(shù)組可以理解為一位數(shù)組組成的數(shù)組p = a;那么p + 1是向后跳了四個(gè)整形(int)16個(gè)字節(jié)a[4][2]的地址比p[4][2]的地址高4,所以結(jié)果為-4;計(jì)算機(jī)存數(shù)據(jù)是以補(bǔ)碼的形式存儲(chǔ):-4的存儲(chǔ)100000000 00000000 00000000 00000100 - 原碼111111111 11111111 11111111 11111011 - 反碼111111111 11111111 11111111 11111100 - 補(bǔ)碼以%p的形式輸出,就是以16進(jìn)制的形式輸出,結(jié)果為:FF FF FF FC6、程序運(yùn)行的結(jié)果是什么呢?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)); return 0;}解析:與前面幾題有所雷同,再次不再過多贅述只強(qiáng)調(diào)一點(diǎn):&aa得到的是整個(gè)二維數(shù)組的地址,對(duì)其+ 1是跳過整個(gè)二維數(shù)組。
可以自己嘗試解決7、程序運(yùn)行的結(jié)果是什么呢?int main(){ char* a[] = { "work","at","alibaba" }; char** pa = a; pa++; printf("%s\n", *pa); return 0;}解析:注意: 形如 char* p = "abcdefg";這樣的p為字符指針,存放的是字符串首元素的地址同時(shí)它是只 讀 的 ,是不能被修改的如果 *p = ‘w’;這樣操作的話,編譯器報(bào)警告訪問權(quán)限沖突)a[]就是一個(gè)指針數(shù)組,里面存放的都是字符指針a是數(shù)組名是數(shù)組首元素的指針,char** pa;說明pa是個(gè)指針,這個(gè)指針指向的類型是個(gè)字符指針 pa++;就是相當(dāng)于pa + 1,首元素向后跳動(dòng)一個(gè)字符指針,便是"at"這個(gè)字符串的首地址8、程序運(yùn)行的結(jié)果是什么呢?int main(){ char* c[] = { "ENTER","NEW","POINT","FIRST" }; char** cp[] = { c + 3,c + 2,c + 1,c }; char*** cpp = cp; printf("%s\n", **++cpp);//*cp[1] -> *(c + 2) -> c[2] printf("%s\n", *-- * ++cpp + 3); printf("%s\n", *cpp[-2] + 3);//* 的優(yōu)先級(jí)比 +的優(yōu)先級(jí)第 printf("%s\n", cpp[-1][-1] + 1); return 0;}解析:一開始布局:c中放的是字符串首地址。
cp中放的是c中元素得地址cpp放的是cp首元素地址cpp - 解釋:補(bǔ)充:操作符的優(yōu)先級(jí):++ 高于 * 高于 + 高于 - 先對(duì)cpp自增一次,此時(shí)cpp指向了(c + 2)的位置,一次解引用*操作就拿到了cp數(shù)組中的(c + 2),再次解引用*操作就拿到了c數(shù)組中第3個(gè)元素,第三個(gè)是個(gè)元素是字符指針,這個(gè)字符指針存放的是POINT這個(gè)字符串的首地址,%s拿到了POINT首地址向后打印,所以結(jié)果為POINT * ++cpp + 3 - 解釋:cpp現(xiàn)在原只向的(c + 2)位置上自增1,此時(shí)指向了(c + 1)的位置上,解引用*一次便拿到了(c + 1),因?yàn)?-- 的優(yōu)先級(jí)比+高,先執(zhí)行 -- ,(c + 1)自減變成了c,再解引*用一次,就拿到c[]數(shù)組的第一個(gè)元素,第一個(gè)元素存的是ENTER的首地址,再對(duì)首地址 + 3,跳過三個(gè)字符,指向了Es拿到了E的地址向后打印,結(jié)果就是ERcpp[-2] + 3 - 解釋:*cpp[-2] + 3 <==> *(*(cpp - 2)) + 3,cpp在指向原來的(c + 1)位置,而(cpp - 2)向前跳動(dòng)兩個(gè)char**的元素指向了(c + 3)的位置,但是cpp本身的值沒變,這時(shí)對(duì)(cpp - 2)解引用*一次就拿到了(c + 3),再對(duì)(c + 3)解引用*一次就拿到了c[]數(shù)組中的最后一個(gè)元素,c[]數(shù)組中的最后一個(gè)元素存的是FIRST字符串的首地址,對(duì)其+3就是跳過三個(gè)字符,指向了S。
s拿到了S的地址向后打印,結(jié)果就是STcpp[-1][-1] + 1 - 解釋:cpp[-1][-1] + 1 <==> *(*(cpp - 1) - 1) + 1,cpp在指向原來的(c + 1)位置,(cpp - 1)向前跳動(dòng)一個(gè)char**的元素指向了(c + 2)的位置,但是cpp本身的值沒變,這時(shí)對(duì)(cpp - 1)解引用*一次就拿到了(c + 2),再對(duì)(c + 2) - 1得到了(c + 1),再對(duì)(c + 1)解引用*一次就拿到了c[]數(shù)組中的第二個(gè)元素,c[]數(shù)組中的第二個(gè)元素存的是NEW這個(gè)字符串的首地址,對(duì)其 +1就是跳過一個(gè)字符,指向了Es拿到了E的地址向后打印,結(jié)果就是EW 9、輸入10個(gè)整數(shù),將其中最小的數(shù)與第一個(gè)數(shù)對(duì)換,把最大的數(shù)與最后一個(gè)數(shù)對(duì)換最后輸出這10個(gè)整數(shù)答案:#include





![[精編]吳教人[]13號(hào)](/Images/s.gif)






