(番外篇)指針的一些相關習題講解(速進,干貨滿滿)(2)

前言:

? 小編感覺最近有點太墮落,于是我開始從事這篇文章的撰寫,現在也是進入七月份了,我現在文章開頭定一個小目標,我決定在七月份發布至少十篇文章,希望我可以說到做到(我前面就口頭欠了不少文章),好了,不多廢話了,下面進入今天的主題,對于指針習題的演練,這些題都是小編在上課時聽到的題,為了加強自己的記憶,于是我將此作為文章的主題,下面進入正文嘍

目錄:

1.題目一

2.題目二

3.題目三

4.題目四

5.題目五

6.題目六

7.題目七

?正文:

1.題目一

int main()
{int a[5] = { 1, 2, 3, 4, 5 };int* ptr = (int*)(&a + 1);printf("%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的結果是什么?

? 各位先來思考一下這個題怎么做,老規矩,小編依舊是先解釋,后做題,下面進入解釋環節:首先我們先看printf函數,里面第一個元素是*(a + 1),此時a是數組名,它不是那兩種特殊情況,所以此時數組名代表的就是數組第一個元素,加1后對應著數組第二個元素的地址,在進行解引用操作后,會直接呈現第二個元素,那么就是2了;之后是第二個元素,此時涉及到了ptr,所以我們先看ptr這個指針,它代表著進行整型強制類型轉換以后的(&a + 1),不難發現,此時數組名符合了第一種特殊情況,所以代表著整個數組的地址,加1后是數組最后一個元素下行的地址,此時指針指向的應該是5后面元素的地址,此時減去1后,又回到了數組第五個元素代表的地址,所以進行解引用操作后,變成了5,為了讓讀者更好的理解這個題目,小編特意的給了圖例進行解釋:

?

? 通過上圖可以清晰的看出小編在文字解釋中所解釋的內容,下面小編展示這個代碼的運行圖:

? 可以看出小編解釋的是正確定,下面廢話不多說,進入下一個題的訓練:

2.題目二?

//在X86環境下
//假設結構體的??是20個字節
//程序輸出的結果是啥?
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

? ? 老規矩,大家先思考幾秒,然后給出解釋,下面開始解釋環節:首先映入我們眼簾的是一個結構體,由于結構體的大小如何計算小編還沒有設計到,所以這里直接給大小了(后面小編會著重強調它的對齊方式的在結構體的文章中),這里我們已經給出了結構體的地址,不過這個地址得強制類型轉換,不然就不是結構體的地址了,下面我們正是看看函數部分,首先是第一個printf函數,這個函數內部是結構體指針加1,記住這個加的1是0x開頭的,所以應該是16進制的方式進行操作的,此時p是指針,指針加數的話代表著它的地址是要加它本身大小倍數的數,所以此時應該加20個字節,并且由于這是16進制儲存的,所最后的結果應該是0x100014;對于第二個printf函數,首先我們先看括號內容,此時括號內容是unsigned long,所以此時的p已經強制類型轉換成無符號的長整型了,此時p可以看作一個整數,對于整數加1的話,那就是真的加1,所以結果應該是0x100001;對于第三個printf語句,此時括號里面的內容是unsigned int*,代表著強制類型轉換成無符號整型的指針,所以此時指針每次加的大小已經改變了,此時加1代表著加4個字節的空間,所以結果應該是0x100004,這個問題小編認為不需要圖來了解,因為這沒有牽扯到指針的遷移,僅僅就牽扯到了指針運算,下面來看看此代碼的運行圖:

? ?讀者朋友無需關注前面是什么,光看末尾數字就好了,此時說明小編解釋沒有錯誤,那么我們加快步伐,直接開始看下一個題的講解!

3.題目三?

int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int* p;p = a[0];printf("%d", p[0]);return 0;
}

? 老規矩,各位先看會題目,我等會做出解釋,下面開始解釋:首先這個題定義的二維數組,然后設置了一個整型指針,此時指針指向二維數組第一行的地址,然后printf函數里面的是p[0],此時其實有第二種寫法,就是*(*p + 0),此時不難看出,這個是指向數組第一個元素的地址,那么我們回頭看看這個二維數組,可能有些讀者會脫口而出,答案是0,但是其實這個說法是錯誤的,仔細看,數組里面每兩個元素用什么圍起來的,是括號,而不是大括號!所以此時我們對于括號里面的內容,其實是逗號表達式,逗號表達式的邏輯是,從左往右依次計算,不過最后的結果是右邊的數,所以其實這個數組在內存中的存放是如下圖所示的:

? 所以可以知道打印出來的結果應該是1,那么很多讀者可能忘記了我們想要規定二維數組行和列具體數應該怎么做,其實這里是要用大括號的,下面是代碼展示:

int a[3][2] = { {0,1 }, {2,3} , {4,5} };

? 下面是在調試界面此數組的存放:

? 所以各位在做相關習題的時候一定要瞪大雙眼,防止出題人給你設置成一個大坑讓你跳進去,我們要做到看到坑直接繞過去,下面不多廢話直接上運行頁:

? ?可以看出小編并沒有說錯,大家一定要在做題不要看題目過于簡單而痛失分數。下面不多廢話,調整心態,下個題來嘍:

4.題目四

//假設環境是x86環境,程序輸出的結果是啥?
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;
}

? 這個題一看就比上面的題復雜了很多,畢竟難度是相加的,在講解這個題之前,小編還想告訴大家,大家在做指針相關習題的時候一定要記得畫圖,畫圖可以幫助我們更好的了解這個題怎么做,小編就在每次在牽扯到指針計算的時候,都會畫上圖來幫助大家理解,其實很顯然,圖文要比文字更好的來幫助人們去理解知識,所以大家在做題的時候一定要畫圖,下面來開始解釋環節了。

? 由于這個題太過復雜,小編先放上a數組的存放圖文來幫助大家去感受a數組內容:

? ?下面我們來正式開始觀看這個代碼,首先我們看到一個老朋友:int (*p)[4],讀者朋友如果已經學完了指針部分,那么很容易看得出這個是數組指針,p代表的是數組,而[4]則代表著里面存放著四個元素,下面我們可以接著看,此時把a首行的地址給了p,此時讀者朋友可能會想,a每個里面存放著5個元素,而p里面卻存放著4個元素,它們如何建立起聯系呢?其實這里不用多考慮,首先,p其實在這里我們可以看做成地頭蛇,有句老話這么說,在我的地盤,是龍只能盤著,是虎也得趴著,所以此時每個p里面都存放每個a所對應的四個元素,此時小編也將p在內存中的存放也放到下面了:

? 下面我們已經畫好了a和p的圖,此題其實已經完成了大半部分了,下面我們來看看printf函數里面的內容,這兩個元素是一樣的,只不過是兩種形式表示著,一個是地址,一個是整型,下面我們先來看看元素是什么,分別是p[4][2]和a[4][2],如果沒有畫圖,可能很難看出來這個具體表示著什么,但是現在我們有了圖,這就好辦了,下面是小編利用圖來表示這兩個元素?

? 此時printf里面存放著是這兩個數的地址,小編之前說過,指針和指針相減,得出來的結果是兩個指針之間相差的元素的個數,這個小編之前寫過的文章說過,下面放上鏈接,感到興趣的讀者朋友可以看一下:深入理解并打敗C語言難關之一————指針(1)-CSDN博客,回歸正題,這兩個數之間相差的個數是4個,但這個是前者減去后者,所以得出來的結果應該是-4,不過現在的重點是第一個元素是要取到它的地址,所以這里牽扯到了原碼反碼補碼的知識,這些知識小編也會在以后的文章說的(欠的文章+1),所以下面通過代碼頁來展示-4的反碼:

//10000000000000000000000000000100  //原碼
//11111111111111111111111111111011 //反碼  (原碼取反)
//11111111111111111111111111111100   //補碼(反碼 + 1)

? 所以的出來結果應該是下面源碼4個為一起通過16進制位數表示出來,應該是0xFFFFFFFC,下面這個題已經講解完畢,下面進入此題目的運行環節:

? 可以看出小編這里并沒有說錯,這個題有點復雜,讀者朋友們如果理解不了的話一定要多看一遍,下面趁熱打鐵,進入下個題目嘍!

?5.題目五

int main()
{int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&a + 1);int* ptr2 = (int*)(*(a + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

? 如果會了上一個題的話,這個題也是會迎刃而解的,老規矩,讀者朋友先思考下這個題,等會小編做出解釋,三,二,一,下面給出解釋:

? 首先,印入我們眼簾的還是一個二維數組,下面小編先來畫一下二維數組的儲存圖來幫助各位取理解:

? 這個二維數組的存放就是如圖所示的(為了直觀小編直接展開成一行了),我們開始看代碼頁,首先我們先看到的是兩個指針,ptr1和ptr2,首先第一個是先對數組名進行取地址操作,此時涉及到了小編之前提到過的特殊情況,所以此時是取到了整個數組的地址,在進行加1就是去到了10以后元素的地址,此時還對他強制類型轉化成了整型指針(可能很多讀者朋友會很奇怪,認為二維數組不也是整型指針嗎,其實二維數組實質是一個數組指針,小編以前可能提到過,如果沒提到過大家記住就好),在看ptr2,此時這個指針同樣也是對括號里面的內容強制類型轉化成整形指針了,下面我們再來看看括號里面的內容,此時是先對a進行加1操作,我們知道,二維數組數組名代表著第一行的地址,所以這個進行加1操作以后直接變成了a[1],在進行解引用操作以后直接變成了第一個元素所代表的地址了,下面為了讓讀者朋友更好的理解這個題目,直接上圖:

? 之后我們繼續往下看,我們來看看printf函數,此時里面同樣也是有兩個元素,第一個是對ptr1 - 1,此時ptr已經是整形指針了,所以減1后對應著10這個元素的地址,然后解引用后會變成10;第二個是ptr2 - 1?,此時ptr2也是整形指針,減去1后代表著5的地址,解引用后是5,下面我們先用圖文解釋,在來放運行圖:

?

? 可以看出小編并沒有說錯,大家在寫題目的時候一定要畫圖,畫圖可以保證大家做題目時更有思路,提高正確率,下面我們進入下一道題:

6.題目六

?

int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;}

? 這個題可能會有一點難度,讀者朋友一定要先仔細看看這個題,畫出相應的圖這個題就好;理解多了,下面小編放上這個題的解析:

? 首先,我們看到了一個數組我,這個數組的類型是char *,所以很顯然這個數組是個指針數組,下面我們圖解這個指針數組:

? 通過上圖可以清晰的看出這個指針數組的具體內容,之后我們接著看代碼,后面的代碼是又設置了一個二級指針pa,這個二級指針儲存著此指針數組首元素地址的地址,接著看下面的代碼,此時是pa++,代表著pa + 1,所以此二級指針變成了儲存第二個元素的地址的地址,然后我們繼續看下面代碼,看出其元素是對二級指針進行解引用,我們知道,二級指針解引用后就變成了其儲存元素的地址,此時由于儲存著字符串,對字符串的打印我們需要獲取字符串的地址,此時正好是第二個元素的地址,所以應該打印出的是"at",下面小編先給圖解,然后給運行圖:

?

? 以上便是運行結果和圖解,所以小編這里又一次得強調下,對于這種題一定要畫圖,畫圖可以幫助我們解決大部分我們無法解決的問題,下面我們趁熱打鐵,迎接本篇文章最后一個習題,此習題與本習題同一個做法,大家一定要理解好這個題的做法:?

題目七

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;
}

? 這個題的難度比上面的難度還要大,大家先看看這個代碼,自己畫圖思考一下,下面小編著重進行解釋了:

? 首先,我們不難發現了這里牽扯到了三個指針,分別是指針數組,二級指針,三級指針,各位先看好這幾個指針,下面小編直接上這三個指針的圖解了,畢竟一個一個寫顯得我有點水字數了:

?

? 下面我們來看看printf語句里都有什么元素,首先看第一個printf里面的元素,里面是 ** ++ cpp,首先我們知道++操作符運算級是很高的,所以此時是cpp先 加 1,然后此時指向了cp[1]的地址,之后二次解引用操作后,變成指向了c[2]的地址,所以是打印了c[2]所代表的字符串,也就是"POINT",下面小編給上圖解:

? ?下面我們再來看看第二個printf函數里面的元素,這個更是復雜:*-- * ++cpp + 3,此時我們一個一個的看,此時是先進行 ++ cpp的操作,經過上面的printf里面cpp進行加1后,此時在進行加1,cpp指向了cp[2]的地址,此時進行解引用操作后就會變成cp[2],之后我們在進行--操作,此時是代表著cp[2]所指向的內容減1,所以此時cp[2]變成了指向c[0]的地址,再次進行解引用操作以后,此時就是變成了c[0],此時再次進行 + 3操作,代表著數組里面的元素加3,所以我們打印數據就開始從E進行打印,所以最后打印的結果應該是“ER”,下面給上圖解:? ? ? 下面我們繼續來看看下一行的代碼,此時里面的元素是 :?*cpp[-2] + 3 ,我們一九從左往右看,此時是先對于cpp進行解引用操作,由于上面進行了兩次 ++ 操作,所以解引用cpp以后里面的元素變成了cp[2],此時有一個[]操作符,其實這個就是再次對cp進行解引用,不過是減2后再解引用,所以此時變成了cp[0],進行解引用后就指向了c[3],此時再次加3代表著里面元素地址加3,所以是從“S”開始打印,最后打印出來的應該是:"ST",下面依舊給上圖解來幫助大家理解:

? 下面我們再來看最后一個printf函數里面的元素,里面是:cpp[-1][-1] + 1 ,我們依舊從左往右看,此時cpp[-1]其實實際代表著* cpp - 1,所以此時是代表著cp[1],之后的[- 1],代表著 * cp[1] - 1,也就是說最后指向的是c[1],此時在進行 + 1操作后,就代表著從“E”開始進行打印,最后呈現的結果是 “EW”,下面我們依舊用圖文進行解釋:

? ?下面我們來放運行結果:

? ? ?可以看出雄小編這個題并沒有說錯,這個題大家一定要好好的去了解,難度系數還是比較大的,這個題也是同樣彰顯了畫圖的重要性,大家在做題時一定要好圖,這樣才不容易出錯,也好找到自己的錯誤。

總結:

??小編也是干完了這篇文章,這也是指針部分的強化篇,指針講解部分到這里就徹底的結束了,相信各位讀者朋友看到小編寫過的指針篇幅,大概也知道了指針的重要性,大家一定要好好掌握指針,到現在開始,我們已經返過了C語言的一座大山,希望各位已經明白了指針。最后,如果文章有什么錯誤,請大家一定在評論區指出,小編會改正自己錯誤的,那么,我們下篇博客見啦!?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/39784.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39784.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39784.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenSSL的一些使用案例

目錄 一、介紹 二、基本使用 1、Shell (1)文件加解密 (2)生成密鑰文件 2、API (1)md5sum (2)AES256加解密 一、介紹 本篇博客重點不是詳細描述 OpenSSL 的用法,只…

什么是校園氣象站

在科技日新月異的今天,氣象觀測不僅局限于專業的氣象機構,它已經走進了我們的校園,成為了學生們探索自然、學習科學知識的重要平臺。 校園氣象站是設置在學校內部,用于進行氣象觀測、數據記錄和科學實驗的設施。它通常由氣象傳感器…

MySQL之應用層優化和備份與恢復(一)

應用層優化 緩存 作為基礎組件的緩存 緩存有可能成為基礎設施的重要組成部分。也很容易陷入一個陷阱,認為緩存雖然很好用,但并不是重要到非有不可得東西。你也許會辯駁,如果緩存服務器宕機或者緩存被清空,請求也可以直接落在數…

常見鎖策略之可重入鎖VS不可重入鎖

可重入鎖VS不可重入鎖 有一個線程,針對同一把鎖,連續加鎖兩次,如果產生了死鎖,那就是不可重入鎖,如果沒有產生死鎖,那就是可重入鎖. 死鎖 我們之前引入多線程的時候不是講了一個加數字的案例么,我們今天以它來舉例 當我們這樣寫的時候會出現什么問題? 分析:第一個synchron…

前端基礎--Vue3

Vue3基礎 VUE3和VUE2的區別 2020年9月18日,Vue.js發布版3.0版本,代號:One Piece 于 2022 年 2 月 7 日星期一成為新的默認版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。體積更小 Vue3.0 打包大小減少41%。 同時Vue3可以更好的支持T…

基于微服務智能推薦健康生活交流平臺的設計與實現(SpringCloud SpringBoot)+文檔

💗博主介紹💗:?在職Java研發工程師、專注于程序設計、源碼分享、技術交流、專注于Java技術領域和畢業設計? 溫馨提示:文末有 CSDN 平臺官方提供的老師 Wechat / QQ 名片 :) Java精品實戰案例《700套》 2025最新畢業設計選題推薦…

vb 學習簡介

vb 第一節 Visual Basic(簡稱VB)是一種高級編程語言,它最初由微軟公司開發,旨在簡化Windows應用程序的開發過程。下面,我們將介紹Visual Basic編程語言的基礎概念和用途,包括其歷史背景、主要特性以及在現代編程中的應用。 歷史背景 Visual Basic起源于1991年,當時微軟…

代碼隨想錄算法訓練營day72 | 117. 軟件構建、47. 參加科學大會

本次題目來自于卡碼網 117. 軟件構建(拓撲排序) python設置默認值 from collections import defaultdict aa defaultdict(int) 拓撲排序:找到入度為0的節點,然后移除。如果最后都能移除,則無環,可以排…

C#發票識別接口,再長的稅號錄入都不怕

“十二金”工程是我國政府在信息化建設中的重要一步,“金稅工程”總稱為中國稅收管理信息系統(CTAIS),是我國電子政務的核心系統之一,是財政的重要環節。十二金”是面向政府辦公業務建立的十二個重點信息應用系統,按“…

解決使用monaco-editor編譯器,編譯器展示內容沒有超過編譯器高度,但是出現滾動條問題

前言: 最近在完成項目時,有使用編譯器進行在線編輯的功能,就選用了monaco-editor編譯器,但是實現功能之后,發現即使在編譯器展示的內容沒有超過編譯器高度的情況下,編譯器依舊存在滾動條,會展示…

計算機網絡--網絡層

一、網絡層的服務和功能 網絡層主要為應用層提供端對端的數據傳輸服務 網絡層接受運輸層的報文段,添加自己的首部,形成網絡層分組。分組是網絡層的傳輸單元。網絡層分組在各個站點的網絡層之間傳輸,最終到達接收方的網絡層。接收方網絡層將運…

如何在 Java 應用中使用 Jedis 客戶端庫來實現 Redis 緩存的基本操作

本人詳解 作者:王文峰,參加過 CSDN 2020年度博客之星,《Java王大師王天師》 公眾號:JAVA開發王大師,專注于天道酬勤的 Java 開發問題中國國學、傳統文化和代碼愛好者的程序人生,期待你的關注和支持!本人外號:神秘小峯 山峯 轉載說明:務必注明來源(注明:作者:王文峰…

構建高效盲盒小程序:數據庫設計、安全策略與性能優化

在移動互聯網時代,盲盒經濟以其獨特的魅力迅速崛起,成為連接消費者與商品的新橋梁。盲盒小程序作為這一趨勢的載體,不僅要求用戶體驗流暢,還需確保數據安全與性能卓越。本文將從數據庫設計、安全策略及性能優化三個方面&#xff0…

堆與棧的概念(RTOS)

目錄 #堆在RTOS的概念 #相關代碼表示 #堆相關特點 #棧在RTOS中的概念 #棧的代碼表示 #棧的相關特點 #為什么每個RTOS任務都要有自己的棧 前言:本篇參考韋東山老師的RTOS,連接放在最后 #堆在RTOS的概念 本文所指的堆與棧并不是數據結構中&#xff…

【unity實戰】在Unity中使用有限狀態機制作一個敵人AI

最終效果 文章目錄 最終效果前言有限狀態機的主要作用和意義素材下載邏輯圖敵人動畫配置優雅的代碼文件目錄狀態機代碼定義敵人不同狀態切換創建敵人效果更多的敵人參考源碼完結 前言 有限狀態機以前的我嗤之以鼻,現在的我逐幀分析。其實之前我就了解過有限狀態機&…

2.(vue3.x+vite)調用iframe的方法(vue編碼)

1、效果預覽 2.編寫代碼 (1)主頁面 <template><div><button @click="sendMessage">調用iframe,并發送信息

【udp報文】udp報文未自動分片,報文過長被攔截問題定位

問題現象 某局點出現一個奇怪的現象&#xff0c;客戶端給服務端發送消息&#xff0c;服務端僅能收到小部分消息&#xff0c;大部分消息從客戶端發出后&#xff0c;服務端都未收到。 問題定位 初步分析 根據現象初步分析&#xff0c;有可能是網絡原因導致消息到服務端不可達&a…

【C語言】文件的順序讀寫

©作者:末央&#xff06; ©系列:C語言初階(適合小白入門) ©說明:以凡人之筆墨&#xff0c;書寫未來之大夢 目錄 前言字符輸入輸出函數 - fgetc和fputc文本行輸入輸出函數 - fgets和fputs格式化輸入輸出函數 - fscanf和fprintf 前言 對文件數據的讀寫可以分為順序…

Unity3D 打造基于AStar的尋路與導航詳解

在游戲開發中&#xff0c;尋路與導航是一個至關重要的功能&#xff0c;它能夠使游戲角色自動找到最優路徑&#xff0c;避開障礙物&#xff0c;實現自動導航&#xff0c;從而提升游戲體驗。AStar&#xff08;A*&#xff09;算法作為一種廣泛應用的尋路算法&#xff0c;因其高效性…

關于多線程的使用方法

多線程在python中應用比較廣泛&#xff0c;但是因為python中有GIL鎖的緣故&#xff0c;在多線程中看起來是并發的執行的&#xff0c;在宏觀上是并發執行的&#xff0c;但是在微觀上是一個接著一個執行。 在python中使用多線程比較簡單&#xff0c;是一套固定的模版。 from qu…