[英]C - Incompatible pointer type assignment: why is it a warning?
我正在看 K&R 第 2 版,它說(在第 5.4 節中):
除了 void *,將一個類型的指針分配給另一種類型的指針而不進行強制轉換是不合法的。
但是,執行此操作時,gcc 和 clang 只會發出警告,而不是編譯器錯誤:
int *ip;
char *cp;
ip = cp;
我在 gcc 手冊上沒有看到任何說明這是默認編譯器擴展的內容。 使用 C++ 編譯器確實會引發編譯錯誤。
請注意,這本書在 A6.6 節中似乎自相矛盾,它說
指向一種類型的指針可以轉換為指向另一種類型的指針。
盡管我給了它懷疑的好處,因為它可能指的是使用顯式強制轉換從指針類型轉換為另一種。
int *ip;
char *cp;
ip = cp;
賦值是違反約束的,這意味着符合標准的編譯器必須發出診斷,就像它必須為語法錯誤所做的那樣。 (有關簡單分配的要求,請參閱http://port70.net/~nsz/c/c11/n1570.html#6.5.16.1 。)該診斷可能是非致命警告。 C 標准從不要求拒絕代碼,除非它有#error
指令。 它沒有將代碼稱為“合法”或“非法”。
如果您使用gcc -std=c11 -pedantic-errors
進行編譯,gcc 會將其視為致命錯誤。 請注意,默認情況下 gcc 不是完全符合 C 的編譯器,盡管它在這種情況下的行為是符合要求的。
通過強制轉換(顯式轉換),分配將是合法的:
ip = (int*)cp;
但如果cp
的值不確定或轉換導致無效的int*
值(例如,由於 alignment),它可能會導致未定義的行為。
K&R 中的描述是正確的,盡管措辭有點不正式。 它說:
除了 void *,將一個類型的指針分配給另一種類型的指針而不進行強制轉換是不合法的。 如果“合法”是指“不違反約束或語法規則”,這是正確的。 C 標准本身並沒有使用“合法”一詞,但說某事違反約束與說某事是非法的一樣接近。
是的,這個:
指向一種類型的指針可以轉換為指向另一種類型的指針。 確實是指使用強制轉換的轉換——或者在轉換為
void*
的情況下不使用強制轉換。
(我個人的偏好是將語法錯誤和約束違規視為致命錯誤,但大多數編譯器默認情況下相對寬松。這可能是出於歷史原因。在語言的早期版本中,將一種類型的指針分配給沒有強制轉換的另一種類型的指針是有效的,並且從來沒有一個好時機通過拒絕舊代碼來破壞它。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.