[英]If variable a is a char array is char* p = &a defined behaviour in C++
我一直認為:
char a[10];
char* p = &a;
是錯誤的,應改為以下之一:
char a[10];
char* p = a; // OR
char* p = &a[0];
我希望我可以在這里找到線程,所以我正在閱讀說p =&a;。 是有效的,並且是針對C語言而不是C ++。
我一直在思考,顯然:
char* p = new char[10];
char* p1 = &p; // Is wrong
但是,當在堆棧空間中將數組創建為局部數組時,根據我的直覺, a
, &a
和&a[0]
都具有相同的值/地址似乎是合理的。 我不得不說,我一直都在關注C ++,但並沒有看到它是通過這種方式完成的,這就是為什么當我開始研究CI時很快將其稱為錯誤,但是我確信它不在C中(很好的驗證對此也將不勝感激)。 我只是想知道在C ++中是否也是如此,因為據我所記得,在C ++中通常是另外兩種方式之一,而這種方式(如果我的想象力不是很強的話)似乎是在C中完成的。
編輯:這是一個非常愚蠢的問題。 我的困惑來自於我的Visual Studio編譯器使用C編譯而不是C ++編譯的事實,因此我認為這方面的語言有所不同。 我不會刪除該問題,因為它已經有了答案。
char a[10];
char* p = &a;
在C中確實是錯誤的。
特別是(所有引用均參考ISO 9899:1999(C99),並且所有強調均歸我所有):
6.7.8(初始化)/ 11說:
標量的初始化程序應為單個表達式,可以選擇用大括號括起來。 對象的初始值是表達式的初始值(轉換后); 應用與簡單賦值相同的類型約束和轉換 ,將標量的類型作為其聲明類型的非限定版本。
6.5.16.1(簡單分配):
約束條件
- 以下條件之一應成立:
- 左操作數具有合格或不合格的算術類型,而右具有算術類型;
- 左操作數具有與右類型兼容的結構或聯合類型的合格或不合格版本;
- 這兩個操作數都是指向兼容類型的合格或不合格版本的指針 ,並且左側指向的類型具有右側指向的類型的所有限定符;
- 一個操作數是指向對象或不完整類型的指針,另一個是指向
void
的合格或不合格版本的指針,並且左側指向的類型具有右側指向的所有類型的限定符;- 左邊的操作數是指針,右邊的是空指針常量; 要么
- 左操作數的類型為
_Bool
,右為指針。
僅黑體部分適用; 我們沒有使用任何算術或struct / union類型,沒有void
或_Bool
,也沒有null指針常量。
有問題的類型在左邊是char *
(指向char
指針),在右邊是char (*)[10]
(指向char
array [10]的指針)。 指針類型的兼容性定義如下:
6.7.5.1(指針聲明符)/ 2:
為了使兩個指針類型兼容,兩者都應具有相同的資格,並且都應是指向兼容類型的指針 。
指向的類型分別是char
和char [10]
。
但是現在我們被困住了。 有6.2.7(兼容類型和復合類型)/ 1:
如果兩個類型相同,則它們具有兼容類型 。 用於確定兩種類型是否兼容的其他規則,在6.7.2中針對類型說明符進行了描述,在6.7.3中針對類型限定符進行了說明,在6.7.5中針對聲明符進行了描述。
char
和char [10]
顯然不同。 所有在6.7.5中兼容類型的聲明器規則都說“ 使兩個指針類型兼容... ”,“ 使兩個數組類型兼容... ”,“ 使兩個函數類型兼容... ” ,但是非數組類型無法與數組類型兼容。
因此,這些類型不兼容,並且char *p = &a
違反了6.5.16.1中的約束。
5.1.1.3(診斷):
如果預處理翻譯單元或翻譯單元包含違反任何語法規則或約束的條件 ,即使該行為也被明確指定為未定義或實現,則符合條件的實現應至少產生一條診斷消息 (以實現定義的方式標識)定義。
這意味着需要警告或錯誤消息。 如果您的編譯器不生成一個,則它不是實際的C編譯器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.