assigning a value to a long long integers using gcc on sparc solaris
题
I came across something that I think rather strange. The test program
int main(int argc, char* argv[])
{
cout<<"hello"<<endl;
long unsigned l = 0x12345678;
long long unsigned ll = 0x12345678;
cout<<sizeof(l)<<endl;
cout<<sizeof(ll)<<endl;
};
output is:
hello
4
8
No surprises there. The long int
has a size of 4 bytes and the long long
has a size of 8 bytes.
However, when I change it so that the long long is assigned
long long unsigned ll = 0x123456789;
at compile time I get
error: integer constant is too large for "long" type
Now this same test does compile if I force a 64 bit build using the option -m64
. Am I doing something wrong or is this a bug in GCC?
解决方案
Change that to
long long unsigned ll = 0x123456789ULL; // notice the suffix
Without the suffix, the literal is bigger than the maximum unsigned long
value on your machine, and that, according to C++03 (but not C++11, which has long long
), is undefined behavior. This means that anything can happen, including a compile-time error.
It's also worth nothing that there's no long long
in C++03, so it's not guaranteed to work, you're relying on an extension. You'd probably better be off using C++11 instead.
其他提示
The thing here is that many people seem to look at a line of code like your:
unsigned long long ll = 0x123456789; /* ANTI-PATTERN! Don't do this! */
and reason "oh, the type is unsigned long long
, so the value is unsigned long long
and it gets assigned", but that's just not how C works. Literals have their own type, that doesn't depend on the context in which they're being used. And the type of integer literals is int
.
This is the same fallacy as when folks do:
const double one_third = 1 / 3; /* ANTI-PATTERN! Don't do this! */
Thinking "the type on the left is double
, so this should assign 0.3333333...". That's just (again!) not how C works. The types of the literals being divided is still int
, so the right hand side evaluates to exactly 0, which is then converted to double
and stored in the one_third
variable.
For some reason, this behavior is deeply non-intuitive to many people, which is why there are many variants of the same question.