Jacob Pollack Jacob Pollack - 1 month ago 9
C Question

In C, sizeof operator returns 8 bytes when passing 2.5m but 4 bytes when passing 1.25m * 2

I do not understand why the

sizeof
operator is producing the following results:

sizeof( 2500000000 ) // => 8 (8 bytes).


... it returns 8, and when I do the following:

sizeof( 1250000000 * 2 ) // => 4 (4 bytes).


... it returns 4, rather than 8 (which is what I expected). Can someone clarify how
sizeof
determines the size of an expression (or data type) and why in my specific case this is occurring?

My best guess is that the
sizeof
operator is a compile-time operator.

Bounty Question: Is there a run time operator that can evaluate these expressions and produce my expected output (without casting)?

Answer

2500000000 doesn't fit in an int, so the compiler correctly interprets it as a long (or long long, or a type where it fits). 1250000000 does, and so does 2. The parameter to sizeof isn't evaluated, so the compiler can't possibly know that the multiplication doesn't fit in an int, and so returns the size of an int.

Also, even if the parameter was evaluated, you'd likely get an overflow (and undefined behavior), but probably still resulting in 4.

Here:

#include <iostream>
int main()
{
    long long x = 1250000000 * 2;
    std::cout << x;
}

can you guess the output? If you think it's 2500000000, you'd be wrong. The type of the expression 1250000000 * 2 is int, because the operands are int and int and multiplication isn't automagically promoted to a larger data type if it doesn't fit.

http://ideone.com/4Adf97

So here, gcc says it's -1794967296, but it's undefined behavior, so that could be any number. This number does fit into an int.

In addition, if you cast one of the operands to the expected type (much like you cast integers when dividing if you're looking for a non-integer result), you'll see this working:

#include <iostream>
int main()
{
    long long x = (long long)1250000000 * 2;
    std::cout << x;
}

yields the correct 2500000000.

Comments