35

I have two structs defined as follows:

struct EmptyStruct{

};

struct StructEmptyArr{
    int arr[0];
};

int main(void){
    printf("sizeof(EmptyStruct) = %ld\n", sizeof(EmptyStruct));
    printf("sizeof(StructEmptyArr) = %ld\n", sizeof(StructEmptyArr));

    return 0;
}

Compiled with gcc (g++) 4.8.4 on Ubuntu 14.04, x64.

Output (for both gcc and g++):

sizeof(EmptyStruct) = 1
sizeof(StructEmptyArr) = 0

I can understand why sizeof(EmptyStruct) equals to 1 but cannot understand why sizeof(StructEmptyArr) equals to 0. Why are there differences between two?

haccks
  • 104,019
  • 25
  • 176
  • 264
duong_dajgja
  • 4,196
  • 1
  • 38
  • 65
  • 13
    The latter is not a valid struct, so the compiler makes up a value of its own by adding features to the c++ language. The idea probably is that sizeof(struct)+sizeof(array) will yield a pointer just past the array and (char*)structpointer+sizeof(struct) gives the first element of the array. – Johannes Schaub - litb Jul 19 '17 at 15:19
  • 1
    Related to: https://stackoverflow.com/questions/1626446/what-is-the-size-of-an-empty-struct-in-c, https://stackoverflow.com/questions/9722632/what-happens-if-i-define-a-0-size-array-in-c-c – Jonny Schubert Jul 19 '17 at 15:24
  • 2
    Interesting, because I just did this with gcc version 6.3.0 and got an output of 0 for both. – mgarey Jul 19 '17 at 15:25
  • And I did it again with g++ (same version of 6.3.0) and got sizeof 1 for the empty struct and sizeof 0 for the struct with a 0 size array. – mgarey Jul 19 '17 at 15:28
  • I suggest looking at the assembly code – mgarey Jul 19 '17 at 15:29
  • For C++ see: https://stackoverflow.com/questions/9722632/what-happens-if-i-define-a-0-size-array-in-c-c – Jonny Schubert Jul 19 '17 at 15:30
  • Sum up so far: for C, `EmptyStruct` causes UB; for C++, `StructEmptyArr` causes UB. Am I correct? – duong_dajgja Jul 19 '17 at 15:32
  • 7
    @duong_dajgja: For standard C, `StructEmptyArr` is a syntax error (there must be at least one member in the structure C11 §6.7.2.1 ¶2), as is `EmptyStruct` (zero size arrays are not permitted in standard C; C11 §6.7.6.2 ¶1). GCC has extensions that may make them acceptable, but the standard says "No". – Jonathan Leffler Jul 19 '17 at 15:35
  • 1
    @mgarey I suspect this won't actually help, the compiler (should) will replace the sizeof call with a literal value matching that printed out. – Michael Shaw Jul 19 '17 at 15:45
  • 5
    In passing: the result of `sizeof` operator is a size_t, so you should be using `%zu` or similar, not `%ld`. – Toby Speight Jul 19 '17 at 15:50
  • gcc and g++ will whinge about the zero-size array, if you ask it to: `gcc -std=c11 -Wall -Wextra -Wpedantic` or `g++ -std=c++17 -Wall -Wextra -Wpedantic`. – Toby Speight Jul 19 '17 at 15:57

2 Answers2

40

In C, the behavior of a program is undefined if a struct is defined without any named member.

C11-§6.7.2.1:

If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined.

GCC allows an empty struct as an extension and its size will be 0.


For C++, the standard doesn't allow an object of size 0 and therefore sizof(EmptyStruct) returns a value of 1.
Arrays of zero length are not supported by standard C++¹, but are supported as an extension by GNU and the sizeof operator will return 0 if applied.


1. § 8.5.1-footnote 107) C++ does not have zero length arrays.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    But he says that he understands the reason for why the empty struct has its size. And the struct that *does* have a named member has the confusing size. – Johannes Schaub - litb Jul 19 '17 at 15:29
  • @michael clearly the code is not ISO C, because he uses the tag withithout the tag namespace qualifier – Johannes Schaub - litb Jul 19 '17 at 15:30
  • @JohannesSchaub-litb That's moot, I answered a direct question above – Michael Shaw Jul 19 '17 at 15:31
  • 2
    @michael it is not moot because while apples are red, my shirt is blue and in ISO C structs must have a named member, none of this is relevant because the question is not about apples, ISO C, or my shirt – Johannes Schaub - litb Jul 19 '17 at 15:32
  • Please see the comment above by PasserBy, that is the question I was answering. – Michael Shaw Jul 19 '17 at 15:33
  • @duong_dajgja; Updated the answer. – haccks Jul 19 '17 at 15:51
  • I must say that your description is incorrect. Since we are in pedantry mode, I must note that c++ allows objects of size 0 – Johannes Schaub - litb Jul 19 '17 at 15:53
  • 2
    @JohannesSchaub-litb; [Its not my hypothesis](http://www.stroustrup.com/bs_faq2.html#sizeof-empty). Also: *"Unless it is a bit-field (9.6), a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. **Base class subobjects may have zero size**."* § 1.8 (p5) – haccks Jul 19 '17 at 16:02
  • 1
    @hacks you say that the standard forbids objects of size 0, and go on to quote that it allows such. And link to a page that merely says that objects shall have different addresses. If I take numbers 9+0 and 8+0, both are different, yet I added 0 to them. – Johannes Schaub - litb Jul 19 '17 at 16:31
  • @JohannesSchaub-litb; It also says *a most derived object shall have a non-zero size and shall occupy one or more bytes of storage*. – haccks Jul 20 '17 at 13:27
5

https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html

G++ treats empty structures as if they had a single member of type char.

https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure that is really a header for a variable-length object.