在C99之前,如果您没有指定类型,那么int将被暗示,这就是您的代码中发生的情况。即使在C99模式下,它看起来也像在实践中gcc
,clang
只会产生警告。在这种情况下,编译器警告是您的朋友,我在以下情况下尝试过clang -Wall
:
printf( "%zu\n", sizeof(const) ) ;
它警告我:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
这里的所有声明:
static st;
auto au;
register reg;
volatile vl;
const cn;
也有一个隐含的int 类型。
我们可以看到C99 移除了隐含的 int假设:
缺少类型说明符的声明不再隐式假定为 int。C 标准委员会认为编译器诊断类型说明符的疏忽遗漏比静默处理依赖于隐式 int 的遗留代码更有价值。实际上,编译器可能会显示警告,然后假定为 int 并继续翻译程序。
如果我们看一下C99 标准草案, 前向部分第5段包括以下内容:
[...]与上一版本相比的主要变化包括:
并具有以下项目符号:
— 删除隐式 int
更新
那么为什么不sizeof
喜欢static和auto之类的存储类说明符,但可以使用const和volatile之类的类型限定符,这种行为似乎与声明的工作方式不一致,隐式 int假设是否仍然有效?
好吧,如果我们看一下标准草案部分sizeof
中的语法,它如下所示:6.5.3
sizeof unary-expression
sizeof ( type-name )
因此,类型限定符和存储类说明符都不是表达式,但类型限定符是type-name,如果我们查看部分type-name6.7.6
的语法如下:
type-name:
specifier-qualifier-list abstract-declaratoropt
并6.7.2.1
为我们提供了specifier-qualifier-list的语法,如下所示:
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt <- Bingo allows type qualifier
所以我们可以看到即使类型被显式指定为intsizeof
,也只是不接受存储类说明符,所以即使以下是错误的:
printf( "%zu\n", sizeof(static int) ) ;
并clang
告诉我们:
error: expected expression
printf( "%zu\n", sizeof(static int) ) ;
^
而且我们可以进一步看到,如果没有,类型名称将无法sizeof
使用()
:
printf( "%zu\n", sizeof int ) ;
产生错误:
error: expected expression
但正如我之前在这里解释的那样,一元表达式可以使用。()