這個問題在這里已經有了答案: 將資料復制/掃描/讀取到未初始化的指標時崩潰或“分段錯誤” (5 個回答) 8 天前關閉。
你能解釋一下,為什么這個程式有效:
#include<stdio.h>
int main()
{
struct first{
char *name;
int a;
};
struct second{
struct first *second;
int z;
};
struct first *FIRST, C;
FIRST = &C;
struct second *SECOND, b;
SECOND = &b;
SECOND->second->a = 9;
printf("%d", SECOND->second->a);
return 0;
}
雖然這不會:
#include<stdio.h>
int main()
{
struct first{
char *name;
int a;
};
struct second{
struct first *second;
int z;
};
//struct first *FIRST, C;
//FIRST = &C;
struct second *SECOND, b;
SECOND = &b;
SECOND->second->a = 9;
printf("%d", SECOND->second->a);
return 0;
}
總之,你能告訴我為什么我需要在上面的代碼中添加這兩行注釋掉嗎?我是這個領域的初學者。所以,如果你能幫助我,那將是非常好的。
提前致謝!
uj5u.com熱心網友回復:
這兩個程式都有未定義的行為。
在具有 struct second 型別的物件 b 中
struct second *SECOND, b;
具有指標型別的資料成員 second 未初始化并且具有不確定的值。所以在這個陳述句中取消參考這個指標
SECOND->second->a = 9;
導致未定義的行為。
如果物件 b 被初始化為例如,第一個程式可能是正確的
struct second *SECOND, b = { FIRST };
uj5u.com熱心網友回復:
簡短回答:因為您的代碼是非法的,所以編譯器無法理解您的意思。
在兩個代碼片段中,都SECOND->second指向無處(您沒有為其賦值)并且SECOND->second->a您正在取消參考SECOND->second. 它被稱為未定義行為(UB)。解釋如下。
C 語言的 ISO 標準努力為編譯器優化代碼留出空間。他們的努力包括向編譯器提供一些強有力的假設(某些事情不應該發生)。
ISO 標準不要求編譯器對相同型別的 UB 執行一致的操作。它假裝這種規則的變化永遠不會發生,因此它可以愉快地調整您的代碼以更快地運行。它不一定不能列印 9,但您不能依賴它,因為它可能會失敗甚至導致難以診斷的問題。(實際上,您的兩個代碼片段在我的環境中都無法列印 9。)
如果您打開(確切地說是不關閉)編譯器的警告選項,它會為此警告您。只是不要這樣寫你的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/361013.html
