在回答关于sizeof()的问题时,为了看看GCC如何处理,我编写了以下代码:
#include<stdio.h>
#include<stddef.h>
#include<limits.h>
int main(int ac, char *argv[])
{
printf("%zu\n", sizeof(9999999999999999999999999999999999999999999999999999) );
printf("%zu %zu \n", sizeof(int), sizeof(long long));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编制时,海湾合作委员会(4.1.2)发出警告(如预期):
t.c:8:24: warning: integer constant is too large for its type
t.c: In function main:
t.c:8: warning: integer constant is too large for long type
Run Code Online (Sandbox Code Playgroud)
输出是:
16
4 8
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会怎么说这sizeof(9999999999999999999999999999999999999999999999999999)是16?无论多大numnber,对于任何大于的整数文字,它总是16 LLONG_MAX.在我的64位平台sizeof(long)上等于sizeof(long long).
为什么海湾合作委员会这样做?这是某种未定义的行为吗?!
gcc有一个特殊的非标准类型__int128,它是一个128位(16字节)的整数.因此sizeof(__int128)会返回16.它的接缝就像你的超大常数被视为这种__int128类型.请考虑以下代码:
typeof(9999999999999999999999999999999999999999999999999999) (*funcptr_a)();
unsigned __int128 (*funcptr_b)();
void dummy() {
funcptr_a = funcptr_b;
}
Run Code Online (Sandbox Code Playgroud)
如果我更改了funcptr_a和funcptr_b声明中的任何类型,则赋值funcptr_a = funcptr_b;会触发警告.对于这种变化,我没有收到警告(64位Linux上的gcc 4.6.3),因此我知道大整数常量的类型是unsigned __int128.
顺便说一下,你的代码输出有clang 3.0(也是64位Linux)
8
4 8
Run Code Online (Sandbox Code Playgroud)
我会说这不是未定义的,而是一个实现定义的行为.引用C99标准(第6.4.4.1节,第56页):
[...]如果整数常量不能由其列表中的任何类型表示,则它可能具有扩展整数类型,如果扩展整数类型可以表示其值.[..]
我们可以问一下gcc本身:
__typeof__ (9999999999999999999999999999999999999999999999999999) var = 1;
printf("%lld\n", var);
Run Code Online (Sandbox Code Playgroud)
sizes.c:10:5: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘__int128’ [-Wformat]
Run Code Online (Sandbox Code Playgroud)
所以gcc选择 - 如果支持 - __int128过大的十进制常量的类型.