sizeof()在C(GCC)中的行为

P.P*_*.P. 5 c gcc sizeof

在回答关于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).

为什么海湾合作委员会这样做?这是某种未定义的行为吗?!

Cli*_*nna 7

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页):

[...]如果整数常量不能由其列表中的任何类型表示,则它可能具有扩展整数类型,如果扩展整数类型可以表示其值.[..]


Dan*_*her 6

我们可以问一下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过大的十进制常量的类型.