二維字符數組和指針的相應問題研究


二維字符數組和指針的相應問題研究

在嘗試用C語言實現廣度優先算法時,需要用到支持以二維字符數組為值的哈希表,於是我對自己前面實現的int型鍵值對的哈希表進行再加工,發現在定義二維字符數組和指針時遇到較大問題,特此記錄

shadowfish 2019/10/24

將已知的二維字符數組傳入以儲存

嘗試

一開始,我將待傳入的二維字符數組定義為
char a[][30]={"ABCD","EFDG","12122"};
此代碼創建了char類型3行30列 (3個字符串,每個字符串30個字節) 的二維數組。
接着,我嘗試用一個二級指針指向它
char **ap =a;
並讀取它的第一行字符串
printf("%s",*ap);
編譯,運行到printf("%s",*ap); 時報錯Segmentation fault,即段錯誤,訪問了不可訪問的內存。

原因

*ap的值類型為char* (指向char的指針) ,而它實際存儲的是char型二維數組a的第一行數據的值 (本質是int型數據) ,而不是指向a的第一行數據的首地址。這就導致程序將int型數據當作地址訪問,自然訪問了不可訪問的內存。

補充

char* p;字符指針p相當於一維字符數組printf("%s",p)p指向字符數組首地址,配合"%s"格式化輸出相當於從首地址開始逐個輸出各個字符,到"/0"結束。

解決

既然出現問題的原因是*ap指向了int型數據,那么我們需要讓它指向真正的字符數組首地址。我們將待傳入的二維字符數組定義改為
char *a[30]={"ABCD","EFDG","12122"};
這種定義方式創建了長度為30字符型指針數組(char* []),指針數組里的每個指針指向各個字符數組(字符串)的首地址。
char **ap =a;
**ap指向它后,*ap(即ap[0])存儲的是字符型指針變量(char*)的首地址。
printf("%s",*ap);
此時引用*ap進行輸出,傳遞進的是指向a第一行首地址的字符型指針(char*)(等效於*aa[0]),從而輸出了a第一行的所有字符。

我制作了便於直觀理解的圖表:
二維字符數組和指針的相應問題研究.jpg

技巧

定義變量時,調整*的位置,可以更好地理解
char* a[30];
char* *ap;
若將表示字符型指針(char*)的*貼近char,可以很清楚地看出,a[30]是一個char*類型的數組,即字符型指針數組;*ap是一個char*類型的指針,即指向字符型指針的指針。


延申思考
char *a[30]={"ABCD","EFDG","12122"};
char (*a)[30]={"ABCDEFDG12122"};
char *a={"ABCDEFDG12122"};
上述三種定義方式有很大的區別。
char *a[30]={"ABCD","EFDG","12122"};創建了長度為30char型指針數組,指針數組中的每個指針指向各個字符數組(字符串)的首地址;
char (*a)[30]={"ABCDEFDG12122"};創建了指向一個長度為30char型數組的指針;
char *a={"ABCDEFDG12122"};創建了指向"ABCDEFDG12122"這個被隱式創建的字符數組的首地址的指針。

此處三種方式都為a賦了初值。
char *a[30]={"ABCD","EFDG","12122"};將指針數組里的前三個指針指向三個字符數組(字符串);
char (*a)[30]={"ABCDEFDG12122"};初始化了被a指向的字符數組的前面部分字節,它顯式創建了一個字符數組,a被定義為一個指向長度為30的字符數組的指針。VSCODE的調試器可以直接讀取a指向該字符數組的所有元素值;

char *a={"ABCDEFDG12122"};隱式創建了一個長度為14的字符數組,a被定義為指向這個字符數組首地址的指針,相當於

char b[]={"ABCDEFDG12122"};
char *a=b;

可以看出,顯式和隱式本質上都創建了一個字符數組,並令字符指針指向它的首地址。
不同在,顯式聲明時,VSCODE調試器可以實時獲取a的下標0-29的所有元素的值,即使隨后a指向了長度小於或大於30的字符數組,VSCODE調試器依然能且只能實時獲取a下標0-29的值;
隱式聲明時,VSCODE調試器只能顯示a指向的字符數組首地址的字符值。
由此可以推斷,顯式和隱式聲明在底層的實現是等效的,區別是告訴調試器以不同的方式處理這個指針變量的值。

另:
第二種方式若像第一種方式一樣賦初值
char (*a)[30]={"ABCD","EFDG","12122"};
由於這只是一個一維字符數組,只會存儲"ABCD",后面的字符串不會被存儲。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM