簡體   English   中英

sizeof是否可以返回0(零)

[英]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中的此項

正如伊斯巴達維 提到的 ,空結構。 gcc還允許使用0大小的數組

int a[0];
sizeof(a);

編輯:看到MSDN鏈接后,我嘗試在VS2005中使用空結構,並且sizeof確實返回1。我不確定這是否是VS錯誤,或者規范是否對這種事情有某種靈活性

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM