Reputation: 121347
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("%zu\n", 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?!
Upvotes: 6
Views: 7468
Reputation: 575
Yes, no mystery there. Size of long
and long long
are both 8 bytes for GCC 64-bit.
Upvotes: 0
Reputation: 6608
gcc probably uses the long double
type for very big numbers, for which it uses 80 bits on Intel processors. So it probably stores it in a 128-bit number: You should check sizeof(long double)
.
Note: I explicitly mention gcc because Visual C++ doesn't do that (its long double
type is the same as double
).
Edit: Turns out it's not long double
(and according to the standard C99 6.4.4.1 alinea 6 on integer constants (page 56), isn't allowed to be). See CliffordVienna and Daniel Fischer's answers.
Upvotes: 0
Reputation: 183873
We can ask gcc itself:
__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]
So gcc chooses - if supported - the type __int128
for the too large decimal constant.
Upvotes: 6
Reputation: 8235
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. [..]
Upvotes: 8
Reputation: 19484
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)
Upvotes: 1