P.P
P.P

Reputation: 121347

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("%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

Answers (5)

Aravind
Aravind

Reputation: 575

Yes, no mystery there. Size of long and long long are both 8 bytes for GCC 64-bit.

Upvotes: 0

Medinoc
Medinoc

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

Daniel Fischer
Daniel Fischer

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

CliffordVienna
CliffordVienna

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

luser droog
luser droog

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

Related Questions