3

A colleague of mine inserted a (void) sizeof (char[0]) at the end of a multi line, macro as an alternative to do {...} while (0) apparently. I have looked around but I can't find any reference to it and it surprises me that it even compiles.

Is it valid C? I would love a reference to the std.

evading
  • 3,032
  • 6
  • 37
  • 57
  • If it had been `(void) sizeof(char);`, would you have expected that to compile? – Jeff Mercado Jun 01 '15 at 06:03
  • 4
    How is `(void) sizeof (char[0])` an alternative to `do {...} while (0)`? If `sizeof (char[0])` were valid, it would be `0`. If you want to write `(void)0`, just write `(void)0`. – Keith Thompson Jun 01 '15 at 06:09
  • Alternative in the sense that it forces a semicolon at the end aparently. – evading Jun 01 '15 at 06:41
  • @JeffMercado Yes, I would, since sizeof(char) is one and the cast to void kills warnings about unused. Should I not expect that to compile? I'm here to learn. – evading Jun 01 '15 at 06:59
  • Why would anyone do this? I'm all for using C and not fearing that people don't know the language, but this seems like someone's *trying* to obfuscate things. – unwind Jun 01 '15 at 08:01

2 Answers2

6

If you compile with gcc -pedantic, you'll get a warning message:

warning: ISO C forbids zero-size array [-Wpedantic]

The latest draft of the C standard, N1570, section 6.7.6.2 (Array declarators) paragraph 1 says:

If the expression is a constant expression, it shall have a value greater than zero.

This is part of a constraint, so char[0] is a constraint violation, requiring a diagnostic from any conforming C compiler.

(It's not 100% clear that that particular clause applies to the type name char[0] in the absence of a declared object, but the general idea is that standard C does not support zero-length arrays.)

gcc supports zero-sized arrays as an extension, documented here.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 1
    6.7.6/2 says "Each declarator declares one identifier, ". `char[0]` doesn't declare any identifier, so it's not a declarator and therefore 6.7.6.2's constraints don't apply. (Well, that's what the text seems to say -- whether that was the intent is another matter...) – M.M Jun 01 '15 at 06:32
  • @MattMcNabb: Good point. `char[0]` is a *type-name*. 6.7.7 "Type names" says that a type name "is syntactically a declaration for a function or an object of that type that omits the identifier". I presume the intent is that the same constraint applies -- or perhaps it's stated explicitly somewhere else. – Keith Thompson Jun 01 '15 at 06:44
  • @MattMcNabb: BTW, [the question you linked to](http://stackoverflow.com/questions/30557710/do-parentheses-make-a-difference-when-determining-the-size-of-an-array) in the comment on the now deleted answer doesn't apply; the parentheses are part of the syntax of `sizeof` (as distinct from applying `sizeof` to an expression). – Keith Thompson Jun 01 '15 at 06:45
  • Yeah that was more of a side-track – M.M Jun 01 '15 at 07:56
2

C11 6.5.3.4/2:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type.

/4:

When applied to an operand that has array type, the result is the total number of bytes in the array.

C11 6.7.7 defines type name, especially /2:

In several contexts, it is necessary to specify a type. This is accomplished using a type name, which is syntactically a declaration for a function or an object of that type that omits the identifier.

So char[0] is a type name because it is syntactically a declaration for an object that omits the identifier. (Semantically it's invalid because zero-sized arrays are not allowed, but it is still a type name).


Based on these quotes I would say that sizeof is underspecified. 6.5.3.4/2 doesn't restrict type name to type names that would be a legal declaration if an identifier were included. 6.5.3.4/4 does say "the array" but nobody can agree on what "array" means in C anyway and I don't think this clearly implies anything about char[0].

Based on these quotes I would say that it is inconclusive.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365