在回答关于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;
}
编译时,GCC(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
输出是:
16
4 8
海湾合作委员会如何说sizeof(9999999999999999999999999999999999999999999999999999)
是16?无论numnber
有多大,对于任何大于LLONG_MAX
的整数文字,它总是16。在我的64位平台sizeof(long)
上等于sizeof(long long)
。
GCC为何如此表现?这是某种未定义的行为吗?!
答案 0 :(得分:7)
gcc有一个特殊的非标准类型,叫做__int128
,它是一个128位(16字节)的整数。所以sizeof(__int128)
将返回16.它的接缝就像你的超大常数被视为此__int128
类型。请考虑以下代码:
typeof(9999999999999999999999999999999999999999999999999999) (*funcptr_a)();
unsigned __int128 (*funcptr_b)();
void dummy() {
funcptr_a = funcptr_b;
}
如果我更改了funcptr_a和funcptr_b声明中的任何类型,则赋值funcptr_a = funcptr_b;
会触发警告。我没有收到关于此变体的警告(64位Linux上的gcc 4.6.3),因此我知道大整数常量的类型是unsigned __int128
。
顺便说一句,使用clang 3.0(也是64位Linux)你的代码输出
8
4 8
我会说这不是未定义的,而是实现定义的行为。引用C99标准(第6.4.4.1节,第56页):
[...]如果整数常量不能由其列表中的任何类型表示,则它可能具有 扩展整数类型,如果扩展整数类型可以表示其值。 [..]
答案 1 :(得分:6)
我们可以问gcc本身:
__typeof__ (9999999999999999999999999999999999999999999999999999) var = 1;
printf("%lld\n", var);
sizes.c:10:5: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘__int128’ [-Wformat]
所以gcc选择 - 如果支持 - 类型__int128
表示过大的十进制常量。
答案 2 :(得分:1)
什么是如此神秘?这是最大型的尺寸。你被警告了。
标准所保证的是各种类型的相对大小。
1 == sizeof(char)&lt; = sizeof(short)&lt; = sizeof(int)&lt; = sizeof(long)&lt; = sizeof(long long)
答案 3 :(得分:0)
是的,那里没有神秘感。对于GCC 64位,long
和long long
的大小都是8字节。
答案 4 :(得分:0)
gcc可能会将long double
类型用于非常大的数字,因为它在英特尔处理器上使用80位。因此它可能将其存储在128位数字中:您应该检查sizeof(long double)
。
注意:我明确提到了gcc,因为Visual C ++没有这样做(它的long double
类型与double
相同)。
编辑:原来它不是long double
(并且根据标准C99 6.4.4.1 alinea 6 on integer constants(第56页),不允许)。见CliffordVienna和Daniel Fischer的答案。