Behaviour of sizeof() in C (GCC)

While answering a question on sizeof(), just to see how GCC handles, I wrote the following code:

#include<stdio.h>
#include<stddef.h>
#include<limits.h>

int main(int ac, char *argv[])
{
    printf("%zun", sizeof(9999999999999999999999999999999999999999999999999999) );
    printf("%zu %zu n", sizeof(int), sizeof(long long));
    return 0;
}

When compiled, GCC (4.1.2) issued a warning (as expected):

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

And the output is:

16
4 8

How does GCC say that sizeof(9999999999999999999999999999999999999999999999999999) is 16 ?! No matter how big numnber is, it's always 16 for any integer literal greater than LLONG_MAX . On my 64-bit platform sizeof(long) is equal to sizeof(long long) .

Why does GCC behave this way? Is it some sort of undefined behaviour?!


gcc has a special non-standard type called __int128 , which is a 128bit (16 byte) integer. So sizeof(__int128) will return 16. It seams like your ultra-large constant is treated like this __int128 type. Consider the following code:

typeof(9999999999999999999999999999999999999999999999999999) (*funcptr_a)();
unsigned  __int128 (*funcptr_b)();

void dummy() {
    funcptr_a = funcptr_b;
}

If I change any of the types in the declarations of funcptr_a and funcptr_b, the assignment funcptr_a = funcptr_b; triggers a warning. I don't get a warning (gcc 4.6.3 on 64-bit Linux) for this variation, therefore I know the type of the large integer constant is unsigned __int128 .

Btw, with clang 3.0 (also 64-bit Linux) your code outputs

8
4 8

I'd say this is not undefined but an implementation defined behavior. To quote the C99 standard (Sec. 6.4.4.1, page 56):

[...] If an integer constant cannot be represented by any type in its list, it may have an extended integer type, if the extended integer type can represent its value. [..]


We can ask gcc itself:

__typeof__ (9999999999999999999999999999999999999999999999999999) var = 1;
printf("%lldn", var);
sizes.c:10:5: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘__int128’ [-Wformat]

So gcc chooses - if supported - the type __int128 for the too large decimal constant.


What's so mysterious? That's the size of the largest type. You were warned.

All that's guaranteed by the standard is the relative sizes of the various types.

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

链接地址: http://www.djcxy.com/p/21138.html

上一篇: 数据类型不匹配和编译器冲突

下一篇: C(GCC)中sizeof()的行为