20

I have a structure with no members (for the moment) and I would like to know if it is possible to suppress the warning I get:

warning: struct has no members

Is it possible to add a member and keep the sizeof the struct zero? Any other solution?

Mike
  • 47,263
  • 29
  • 113
  • 177
claf
  • 9,043
  • 17
  • 62
  • 79
  • Why do you need the size to be zero? –  Apr 16 '09 at 09:26
  • 2
    Because I have a private interface (in which I have my zero sized struct because I don't implement a certain functionnality) and a public interface where some of my private struct become opaque and just have to have the same size as private one. – claf Apr 16 '09 at 09:49
  • My build system check the private struct size and create the public struct with a "char _opaque[SIZEOF_PRIVATE_STRUCT]". – claf Apr 16 '09 at 09:50

7 Answers7

26

In c the behaviour of an empty structure is compiler dependent versus c++ where it is part of the spec (explanations here)

C++
A class with an empty sequence of members and base class objects is an empty class. Complete objects and member subobjects of an empty class type shall have nonzero size.

in C it is rather more murky since the c99 standard has some language which implies that truly empty structures aren't allowed (see TrayMan's answer) but many compilers do allow it (e.g gcc).

Since this is compiler dependent it is unlikely that you will get truly portable code in this case. As such non portable ways to suppress the warning may be your best bet.

Community
  • 1
  • 1
ShuggyCoUk
  • 36,004
  • 6
  • 77
  • 101
  • So there is no way to portably avoid this warning? (Else then having a compiler specific #pragma using #ifdef for example) – claf Apr 16 '09 at 09:55
  • Moreover, for GCC Diagnostic Pragmas : "Also, while it is syntactically valid to put these pragmas anywhere in your sources, the only supported location for them is before any data or functions are defined." Which means to me I cannot suppress JUST this warning, am I right? – claf Apr 16 '09 at 09:59
  • 1
    The question is about C, not C++. –  Apr 16 '09 at 11:22
  • 2
    @unwesen (I was pointing out the difference between them (as many people may assume that this is something where they are the same) the pragma stuff is relevant to the OP's problem. My answer is basically "it depends on the compiler sorry" with some specific compiler suggestions and info as to *why* – ShuggyCoUk Apr 16 '09 at 12:52
  • 1
    @claferrir - not if you want to keep the struct actually zero size (though this might not be the case portabbly *anyway*) sorry – ShuggyCoUk Apr 16 '09 at 12:54
  • This changed in C 2011 to make it explicit that a structure had to have at least one member. C 2011 (draft N1570) 6.7.2.1 says “A struct-declaration that does not declare an anonymous structure or anonymous union shall contain a struct-declarator-list.” A struct-declarator-list necessarily has, because of its grammar, at least one name, and, because of the struct-or-union-specifier grammar, appears in a declaration of that name as a member of the structure. – Eric Postpischil Nov 07 '22 at 21:05
25

if you just need the struct symbol for casting and function arguments then just:

typedef struct _Interface Interface;

this will create the symbol for an opaque type.

ebassi
  • 8,648
  • 27
  • 29
  • 3
    THANK YOU! I am trying to test my project on different compilers, and was getting a weird compile error in Borland C++. It was telling me this function that used an empty structure was not a member of the class it was declared in. I've been trying to solve the issue for the last 2.5 hours. It turns out, all I had to do was get rid of the brackets when declaring the empty structure, like you show, and it works fine. Son of a b----. Thanks!! – leetNightshade Aug 14 '12 at 19:28
15

Technically this isn't even valid C.

TrayMan was a little off in his analysis, yes 6.2.6.1 says:

Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.

but tie that with 6.2.5-20, which says:

— A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.

and now you can conclude that structures are going to be one or more bytes because they can't be empty. Your code is giving you a warning, while the same code will actually fail to compile on Microsoft's Visual Studio with an error:

error C2016: C requires that a struct or union has at least one member

So the short answer is no, there isn't a portable way to avoid this warning, because it's telling you you're violating the C standards. You'll have to use a compiler specific extension to suppress it.

Mike
  • 47,263
  • 29
  • 113
  • 177
  • So in this case, is the only solution to use a pointer to void ? `void * var;` and point to anything and also can initialize a dynamic set of elements with `malloc`, how about this solution ? I've done it but it uses a lot of type casting. – R1S8K Apr 04 '21 at 10:51
  • Is there a good way to initialize dynamic set of elements where they could differ in type ? I've done this: `tsk_args = malloc(2*sizeof(uint8_t)+1*sizeof(unsigned char*));` where `tsk_args` is a pointer to void. – R1S8K Apr 04 '21 at 10:52
5
struct zero_information { int:0; };

The above code snippet will yield a non-zero value from sizeof(struct zero_information), but it might help you get what you looking for as 100% of all the storage that is allocated for it, is padding (only accessible through hacks, although I don't remember from the top of my head if acceding the padding is undefined behavior).

koby m.
  • 61
  • 1
  • 2
5

C99 standard is somewhat ambiguous on this, but seems to say that an empty struct should have non-zero size.

6.2.6.1 Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.

TrayMan
  • 7,180
  • 3
  • 24
  • 33
3

Is it possible to add a member and keep the sizeof the struct zero?

Nope. FWIW, C++ allows empty structs but the sizeof() is always non-zero for an empty struct.

Any other solution?

Not any easy ones. It's worth noting that empty structs are only somewhat supported in C and disallowed in C99.

Empty structs are supported in C++ but different compilers implement them with varying results (for sizeof and struct offsets), especially once you start throwing inheritance into the mix.

Adisak
  • 6,708
  • 38
  • 46
2

If you're not requiring "too strict" adherence, you might get away with this:

struct empty {
  char nothing[0];
};

This is a GCC extension, though.

I was kind of hoping I'd be able to use the C99 feature called "flexible arrays", declared like this:

struct empty99
{
  char nothing[]; // This is a C99 "flexible array".
};

but that doesn't work; they require that there is at least one normal struct member first, they can't be the only member.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 3
    Well, GCC accepts empty structures anyway... Appearently with size of 0. On the other hand, it will fail on empty structs as well as with this solution if pedantic is turned on (pedantic warnings + turning them into errors). – Aconcagua Nov 17 '14 at 14:03