[英]Can sizeof return 0 (zero)
sizeof運算符是否有可能在C或C ++中返回0(零)? 如果有可能,從標准的角度來看是否正確?
在C ++中,根據定義,空類或結構的sizeof
至少為1。 從C ++標准的9/3“類”:“類類型的完整對象和成員子對象應具有非零大小。”
在C語言中,除非通過擴展名(或編譯器中的缺陷),否則不允許使用空結構。
這是語法(要求花括號內有一些東西)以及6.7.2.1/7“結構和聯合說明符”中的句子的結果:“如果struct-declaration-list不包含命名成員,則該行為未定義”。
如果允許使用零大小的結構,則它是語言的擴展(或編譯器中的缺陷)。 例如,在GCC中,擴展名記錄在“無成員的結構”中 ,內容為:
GCC允許C結構沒有成員:
struct empty { };
該結構的大小為零。 在C ++中,空結構是該語言的一部分。 G ++將空結構視為具有
char
類型的單個成員。
在C和C ++中, sizeof
永遠不會返回0
。 每次您看到sizeof
評估為0
它都是特定編譯器的錯誤/故障/擴展,與該語言無關。
C中的每個對象都必須具有唯一的地址。 換句話說,一個地址最多只能容納一個給定類型的對象(以使指針解除引用)。 話雖如此,請考慮一個“空”結構:
struct emptyStruct {};
更具體地說,是它們的數組:
struct emptyStruct array[10];
struct emptyStruct* ptr = &array[0];
如果對象確實為空(即,如果sizeof(struct emptyStruct) == 0
),則ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr
,這沒有任何意義。 *ptr
然后會指向哪個對象ptr[0]
或ptr[1]
?
即使結構沒有內容,編譯器也應將其視為一個字節長,以保持“一個地址,一個對象”的原則。
C語言規范(第A7.4.8節)將此要求表述為
當應用於結構或聯合時,(
sizeof
運算符的)結果是對象中的字節數,包括使對象平鋪數組所需的任何填充
由於必須將填充字節添加到“空”對象才能使其在數組中工作,因此sizeof()
必須為任何有效輸入返回至少為1的值。
編輯: C規范的A8.3節將沒有成員列表的結構稱為不完整的類型 ,並且sizeof
的定義專門聲明了狀態(並強調了):
運算符(sizeof) 可能不適用於函數類型, 不完整類型或位域的操作數。
這意味着在空結構上使用sizeof
在尚未定義的數據類型上使用sizeof
一樣無效。 如果您的編譯器允許使用空結構,請注意根據C規范,不允許在它們上使用sizeof
。 如果您的編譯器仍然允許您執行此操作,請了解這是非標准行為,不適用於所有編譯器。 不要依靠這種行為。
編輯:另請參閱Bjarne Stroustrup的FAQ中的此項 。
typedef struct {
int : 0;
} x;
x x1;
x x2;
在MSVC 2010(/ Za / Wall)下:
sizeof(x) == 4
&x1 != &x2
在GCC(-ansi -pedantic -Wall)下:
sizeof(x) == 0
&x1 != &x2
即,即使在GCC中它的大小為零,該結構的實例也具有不同的地址。
ANSI C(C89和C99-我沒看過C ++)說:“應該可以唯一地表示對象的每個字節的地址。” 對於零大小的對象,這似乎是模棱兩可的,因為可以說它沒有字節。
編輯:“沒有聲明符,但只有一個冒號和一個寬度的位域聲明表示未命名的位域。作為這種情況的特殊情況,寬度為0的位域表示沒有其他位域將被打包到放置先前位字段(如果有)的單元中。”
在我看來,對於大小為0的結構(按照c的精神),最好sizeof返回0。 但是程序員在選擇空結構的大小時必須要小心。
但這可能會引起問題。 當定義了此類結構的數組時,則
&arr [1] ==&arr [2] ==&arr [0]
這使他們失去了身份。
我想這並不能直接回答您的問題,無論是否可能。 可能取決於編譯器。 (如上述邁克爾的回答所述)。
我認為它永遠不會在c中返回0,不允許有空結構
這是一個測試,其中sizeof產生0
#include <stdio.h>
void func(int i)
{
int vla[i];
printf ("%u\n",(unsigned)sizeof vla);
}
int main(void)
{
func(0);
return 0;
}
如果您有這個:
struct Foo {};
struct Bar { Foo v[]; }
g++ -ansi
返回sizeof(Bar)==0。clang和intel編譯器也是如此。
但是,這不能用gcc編譯。 我推斷這是C ++擴展。
struct Empty {
} em;
struct Zero {
Empty a[0];
} zr;
printf("em=%d\n", sizeof(em));
printf("zr=%d\n", sizeof(zr));
結果:
em=1
zr=0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.