[英]Segmentation Fault in C dereferencing pointers
我試圖理解C編程中的指針和char數組。 我有一個名為player的結構定義如下:
typedef struct player{
char* name;
float ppm;
} player;
我在Main中有以下內容:
int main()
{
player* head = (player*) malloc(sizeof(player));
char* meName = &(head->name);
(*head).name = "potato";
(*head).name = "Paul";
(*head).ppg =7.6;
//printf("player is named %s\n", *meName); //First print
printf("player is named %s\n", meName); //second print
printf("player is named %s\n", (*head).name); //third print
return 0;
}
為什么我的第一張照片會導致分段錯誤,為什么我的另外兩張照片會輸出以下內容:
player is named k0@
player is named Paul
如果我沒記錯的話, meName
應該指向一個內存地址,然后使用另一個指向同一內存地址的指針來更改該內存地址。 實際上,如果我像打印第二張紙一樣打印它,則會顯示該地址。 當我清楚地將變量設置為指向segFault
其后更改的內存空間時,為什么取消引用會導致segFault
? 為什么不改為Paul
? 而且為什么它會首先引發段錯誤?
另外,我希望對箭頭-> vs *用於解引用指針的解釋有所理解。
這是不正確的,並且您應該收到警告:
char* meName = &(head->name);
meName
是指向char
的指針,而不僅僅是指向char
的指針。 解決方法如下:
char** meName = &(head->name);
當然,打印應該看起來像這樣-即您注釋的方式:
printf("player is named %s\n", *meName);
首先,所有printfs使用%s代碼。 這意味着第二個參數將被解釋為指向表示字符的字節的指針(即地址)。 Printf將打印該字節的值(作為字符),然后打印內存中下一個字節的值,依此類推,直到遇到一個值為0的字節為止。
我將一次打印您的打印報表。
printf("player is named %s\n", *meName);
*meName
表示位置meName
處的字符。 該字符是-128到+127之間的整數。 (實際上是107 -參見下文。)現在,您正在使用107這個數字,就好像它是一個以null終止的字符串的地址(第一個字符)一樣。 可能是該數字不是有效地址,因此當printf
嘗試讀取該地址處的字符(107)時,該字符不在進程的內存范圍內,因此您會遇到分段錯誤。 (通常,分段錯誤意味着您試圖在不允許訪問進程的地址上讀取或寫入內存。)
第二
printf("player is named %s\n", meName);
更好是因為meName至少是一個指針。 那么它指向什么呢? 初始化
meName = &(head->name);
表示meName
是字段head->name
的地址( meName
向該字段)。 請注意,這實際上不是字符,而是指向字符的指針。 因此,發生的情況是printf
打印出head->name
的第一個字節,就好像它是一個字符一樣。 它碰巧打印為k
,因此第一個字節為107( k
的ascii編號)。 然后它打印指針的第二個字節,依此類推,直到碰巧有一個字節為00000000。為什么編譯器接受初始化對我來說仍然不清楚,因為左側的類型是“指向字符的指針”,並且右邊的類型是“指向字符的指針”。 它應該至少產生了一個警告錯誤。
第三版
printf("player is named %s\n", (*head).name);
這將查看地址head
並找到一個結構。 所述的值name
該結構的場是一個五個字節序列的第一個字節的地址'P'
'a'
'u'
'l'
0 printf
遵循該指針值來查找'P'
(其它打印),然后遞增指針,並再次跟隨指針以找到'a'
,依此類推,直到找到0字節,然后停止。
請注意,由於printf
有點特殊,因此編譯器不會檢查其參數類型。 這就是為什么您的第一個printf編譯的原因,即使第二個參數的類型不是char*
因為%s指令指示應該這樣做。
int main()
{
player* head = (player*) malloc(sizeof(player));
char* meName = &(head->name);
(*head).name = "potato";
(*head).name = "Paul";
(*head).ppg =7.6;
//printf("player is named %s\n", *meName); //First print
printf("player is named %s\n", meName); //second print
printf("player is named %s\n", (*head).name); //third print
return 0;
}
該代碼具有嚴重的類型錯誤(如果使用適當的警告級別,則某些錯誤會被編譯器捕獲),並且未使用最佳實踐(並且由於輸入錯誤而無法編譯)。 對比一下
int main(void)
{
player* head = malloc(sizeof *head);
char** pname = &head->name;
head->name = "potato";
head->name = "Paul";
head->ppm = 7.6;
printf("address of player name is %p\n", pname);
printf("player is named %s\n", *pname);
printf("ditto: %s\n", head->name);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.