Before C99, if you did not specify a type, then int is implied, which is what happens in your code. It seems that in practice, even in C99 mode, gcc and clang will only give warnings. This is the case when compiler warnings are your friend, I tried this in clang -Wall :
printf( "%zu\n", sizeof(const) ) ;
and he warns me:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
All announcements here:
static st; auto au; register reg; volatile vl; const cn;
also have an implied int type.
We see that C99 removed the implicit int assumption:
A declaration that lacks a type specifier no longer implies an implied int value. The C standards committee decided that it was more important for compilers to diagnose an unintentional omission of a type specifier than to silently process legacy code based on an implicit int. In practice, compilers can display a warning, then assume int and continue translating the program.
If we look at the draft standard C99 In the fifth section of paragraph 5, the following is stated:
[...] Major changes that occurred in the previous edition include:
and has the following brand:
- remove implicit int
Refresh
So why does sizeof not look like storage class specifiers like static and auto, but in the way with type classifiers like const and volatile, the behavior seems incompatible with how declarations work, and if the implicit int assumption still works?
Well, if we look at the grammar for sizeof in the draft standard section 6.5.3 , this would be the following:
sizeof unary-expression sizeof ( type-name )
Thus, neither the type specifier nor the storage class specifiers are an expression, and the type specifier is the type name, if we look at section 6.7.6 , the grammar for the type name is as follows:
type-name: specifier-qualifier-list abstract-declaratoropt
and 6.7.2.1 gives us a grammar for a list of qualifiers, which looks like this:
specifier-qualifier-list: type-specifier specifier-qualifier-listopt type-qualifier specifier-qualifier-listopt <- Bingo allows type qualifier
So we can see that sizeof simply does not accept storage class specifiers, even if the type is explicitly specified for int, so even the following message is an error:
printf( "%zu\n", sizeof(static int) ) ;
and clang tells us:
error: expected expression printf( "%zu\n", sizeof(static int) ) ; ^
and we can also see that type names will not work with sizeof without () :
printf( "%zu\n", sizeof int ) ;
creates an error:
error: expected expression
but unary expressions work with () , as I explained earlier here .