[英]Should this generate a gcc warning?
K&R C(第二版,第5.5節)指出以下內容(我強調):
char amessage[] = "a message"; /* an array */
char *pmessage = amessage; /* a pointer */
amessage是一個大到足以容納字符序列的數組,'\\ 0'用於初始化它。 可以更改陣列中的單個字符,但是消息將始終引用相同的存儲 。 OTOH, pmessage是一個指針,初始化為指向一個字符串常量; 隨后可以修改指針以指向別處; 但是如果您嘗試修改字符串內容,則結果是不確定的 。
現在,我的問題是,在使用-Wall編譯以下程序時,Linux機器上的gcc 4.6.1(或c99)是否應生成警告:
int main(void) {
char amessage[] = "a message";
char *pmessage = "a message";
pmessage[0] = 'b';
return 0;
}
(我發現gcc不會產生任何警告。如果我正確解釋上述內容,我的期望是它應該。)
盡管您對K&R的引用是正確的,但我不希望這段代碼會產生警告,因為在一般情況下很難跟蹤此類錯誤。
例如,考慮一段代碼,其中的指針最初指向一個可修改的內存塊,然后您對其進行一些操作,然后將其分配為指向字符串文字:
char [] ok = "quick brown fox";
char *ptr = ok;
for (int i = 0 ; i != 5 ; i++) {
*ptr++ = '-'; // OK
}
ptr = "jumps over the lazy dog";
ptr[0] = 'J'; // Bad
對於編譯器,跟蹤這些分配並發出警告非常棘手。 不可能涵蓋所有情況,因為指向字符串文字的指針可能來自外部鏈接函數。
僅僅因為代碼錯誤並不意味着gcc可以為其生成警告。 如果在編譯時可以檢測到所有未定義行為的實例,則沒有理由將該行為保留為未定義。 它可能只是一個強制性錯誤,或編譯為等效的abort();
或類似的。
我同意gcc在這種情況下生成警告很容易。 但是關於:
int main(void) {
char amessage[] = "a message";
char *pmessage = "a message";
if (is_prime(some_constant_with_100_million_digits))
pmessage = amessage;
pmessage[0] = 'b';
return 0;
}
它會調用UB嗎?
它可能沒有警告,因為它是未定義的。
同樣我可以這樣做:
char amessage[] = "a message";
char *pmessage = amessage;
free(pmessage);
它沒有警告,但應該是段錯誤。
我認為警告是針對已定義的行為。
好吧,因為pmessage
不是指向const的指針,所以不希望說什么,在這種情況下,因為它沒有進行足夠的靜態分析(您可以嘗試使用-O
開關進行查看)如果這帶來了更多的洞察力,或者因為在這種情況下沒有人讓它說出任何東西 - 這通常意味着沒有機會從未定義的行為中做出不直觀的優化。
GCC支持-Wwrite-strings ,這將在初始化時引發問題,迫使您將pmessage
指針指向const,隨后使以下行變為非法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.