5

在回答有关 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

GCC 怎么说sizeof(9999999999999999999999999999999999999999999999999999)是 16 ?不管有多大numnber,对于任何大于LLONG_MAX. 在我的 64 位平台sizeof(long)上等于sizeof(long long).

为什么 GCC 会这样?这是某种未定义的行为吗?

4

5 回答 5

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

[...]如果一个整数常量不能用它的列表中的任何类型表示,它可能有一个扩展的整数类型,如果扩展的整数类型可以表示它的值。[..]

于 2013-05-30T10:22:51.117 回答
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太大的十进制常量的类型。

于 2013-05-30T10:23:50.827 回答
1

有什么这么神秘?这是最大类型的大小。你被警告了。

标准所保证的只是各种类型的相对大小。

1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

于 2013-05-30T09:48:26.757 回答
0

是的,没有什么神秘之处。long对于 GCC 64 位,和的大小long long都是 8 个字节。

于 2013-05-30T09:50:26.420 回答
0

gcc 可能将long double类型用于非常大的数字,它在 Intel 处理器上使用 80 位。所以它可能将它存储在一个 128 位数字中:你应该检查sizeof(long double).

注意:我明确提到 gcc 是因为 Visual C++ 没有这样做(它的long double类型与 相同double)。

编辑:事实证明不是long double(并且根据整数常量上的标准 C99 6.4.4.1 alinea 6(第 56 页),不允许这样做)。请参阅 CliffordVienna 和 Daniel Fischer 的回答。

于 2013-05-30T09:58:22.870 回答