9

Why and where does C standard allow this code compile? where is it useful?

struct foo {
  int : 12;
};
The Mask
  • 17,007
  • 37
  • 111
  • 185
  • I was thinking the @Carl Norum's answer useful (as usual) why was it removed? – The Mask Oct 04 '13 at 21:51
  • A comment under the deleted answer gives a C11 citation that such a structure invokes undefined behavior, revealed in ouah's answer. Then a comment is given that the answer is deleted for that reason. – Kaz Oct 05 '13 at 01:52
  • Does this answer your question? [Bitfields in C without variable name](https://stackoverflow.com/questions/16833894/bitfields-in-c-without-variable-name) – malat Apr 04 '23 at 13:07

3 Answers3

6

That would be in §6.7.2.1 Structure and union specifiers

12) A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field.126

The footnote explains why such things exist:

126 An unnamed bit-field structure member is useful for padding to conform to externally imposed layouts.

That being said, the same part of the standard (paragraph 8) also states:

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.

But some compilers (GCC and clang at least) allow this anyway, as an extension.

The use is a bit limited if that's the only bitfield in the struct, but not impossible to use as ouah illustrates.

The standard continues on with another "oddity":

As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bitfield, if any, was placed.

Community
  • 1
  • 1
Mat
  • 202,337
  • 40
  • 393
  • 406
  • And since the behavior is undefined by the standard, it will probably be treated differently by every compiler, just for added confusion^H^H^H^H^H^H^H^H^Hfun. – ChuckCottrill Oct 05 '13 at 03:24
6

This program invokes undefined behavior.

C says:

(C99, 6.7.2.1p7) "[...] If the struct-declaration-list contains no named members, the behavior is undefined."

Now some compilers accept it as an extension. How can this be useful?

For example for Linux kernel famous BUILD_BUG_ON_ZERO macro:

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))

To see what does this macro, you can look here.

Community
  • 1
  • 1
ouah
  • 142,963
  • 15
  • 272
  • 331
  • Though the `BUILD_BUG_ON_ZERO` macro uses a struct type which contains no names, it doesn't look like the trick is relying on this in any way (other than that not using names is more hygienic than using names). They key is that a failed expression produces a negative value for the bitfield size, which is diagnosed. – Kaz Oct 05 '13 at 01:58
  • @Kaz It actually uses it. The macro would not work in GNU C with a named member. C does not allow named bit-field of width of 0, only unnamed bit-field. And GNU C also does not allow it: `gcc` stops translation with an named bit-field of width of 0. – ouah Oct 05 '13 at 02:18
  • but you could add another dummy structure member with a name, surely. – Kaz Oct 05 '13 at 02:33
  • @Kaz No, you cannot add another dummy named member. `BUILD_BUG_ON_ZERO` has to *bug* if `e` is non-zero and has to yield `0` if `e` is `0`. See for example Linux `ARRAY_SIZE` macro implementation which assumes this and uses `BUILD_BUG_ON_ZERO` as an identity element when `e` is `0`. By adding a dummy named member (which cannot have a `0` width as we saw above), you can no longer fill the constraint of having a `BUILD_BUG_ON_ZERO` yielding `0` when `e` is `0`. – ouah Oct 06 '13 at 09:20
  • You can easily bend the expression to return zero. `#define BUILD_BUG_ON_ZERO(e) (, 0)` or `#define BUILD_BUG_ON_ZERO(e) (() * 0)` etc. It doesn't matter what the hack returns; all we care is whether it blows up at compile time or not. – Kaz Oct 07 '13 at 00:25
  • @Kaz ok, if your point is whether it possible to write this macro differently or in a more complicated way, the answer is yes it is possible. – ouah Oct 07 '13 at 08:50
3

Well, according to the language specification, if your program contains a struct type without named members, the behavior is undefined. (To the question of why it is not officially recognized as a constraint violation I have no immediate answer.) It is stated in 6.7.2.1/7

The struct-declaration-list is a sequence of declarations for the members of the structure or union. If the struct-declaration-list contains no named members, the behavior is undefined.

Other than that such declaration is not really "useful" since the only thing it produces is undefined behavior.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • By my understanding, some compilers offer a language extension which permits structures to have anonymous members, and imports the names of those members into the namespace of the enclosing struct. Since the standard doesn't specify that the named members of the interior struct members would be considered named members of the external one, would that imply that the standard would forbid a struct whose members were all anonymous imported structs? – supercat Oct 04 '13 at 21:50
  • @supercat: I'm not sure I understand you correctly. Some compilers do indeed allow anonymous struct members (with the behavior you describe), but this is a non-standard extension. C language does not support anonymous struct members. That's all the standard has to say about it. – AnT stands with Russia Oct 04 '13 at 21:53
  • 1
    I just saw your update. Perhaps my comment above provides a reason it's not a constraint violation: a compiler might as a language extension provide a useful meaning to a struct with no named members. Language constructs which have no defined meaning but for which which some compilers might possibly define some useful meaning are better left as UB than as constraint violations, even if it would be a good idea for any compiler *that doesn't define a useful meaning* to issue a diagnostic. – supercat Oct 04 '13 at 21:53
  • My point is that if the standard says some construct X is undefined behavior, then a compiler vendor can offer a fully-standards compliant compiler which is specified by the vendor to implement X in some useful fashion. By contrast, if the standard says X is a constraint violation, then a standards-compliant compiler would be forbidden from having that construct do something useful. – supercat Oct 04 '13 at 21:57
  • @supercat: Well, firstly, when the language authors anticipate the potential usability of some formally forbidden construct, they usually leave it as "implementation-defined behavior". Secondly, many compilers do provide numerous extensions that are based on constraint-violating code. When it comes to extensions, implementations are allowed to do absolutely anything as long as it does not alter any conforming behavior. – AnT stands with Russia Oct 04 '13 at 21:57