Prior to C99 if you did not specify a type then int would be implied which is what is happening in your code. It looks like in practice even in C99 mode gcc
and clang
will just produce warnings. This is a case where compiler warnings are your friend, I tried this in clang -Wall
:
printf( "%zu\n", sizeof(const) ) ;
and it warns me:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
All the declarations here:
static st;
auto au;
register reg;
volatile vl;
const cn;
also have an implied int type.
We can see that C99 removed the implicit int assumption:
a declaration that lacks a type specifier no longer has int implicitly assumed. The C standards committee decided that it was of more value for compilers to diagnose inadvertent omission of the type specifier than to silently process legacy code that relied on implicit int. In practice, compilers are likely to display a warning, then assume int and continue translating the program.
If we look at the draft C99 standard Forward section paragraph 5 includes the following:
[...]Major changes from the previous edition include:
and has the following bullet:
— remove implicit int
Update
So why does sizeof
not like storage class specifiers like static and auto but is okay with type qualifiers like const and volatile, the behavior seems inconsistent with how the declarations work and should the implicit int assumption still work?
Well if we look at the grammar for sizeof
in the draft standard section 6.5.3
it is as follows:
sizeof unary-expression
sizeof ( type-name )
So neither a type qualifier nor a storage class specifiers is an expression but a type qualifier is a type-name, if we look at section 6.7.6
the grammar for type-name is as follows:
type-name:
specifier-qualifier-list abstract-declaratoropt
and 6.7.2.1
gives us the grammar for specifier-qualifier-list which is as follows:
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt <- Bingo allows type qualifier
So we can see that sizeof
just does not accept storage class specifiers even if the type is explicitly specified to int, so even the following 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 further see that type names won't work with sizeof
without ()
:
printf( "%zu\n", sizeof int ) ;
produces an error:
error: expected expression
but unary expressions work with ()
as I explained previously here.