Why is long long int not as long as promised??

O

Oliver Graeser

I need a >49 bit integer type. tried sizeof(long long), says 8. 8 byte =
64 bit right? but when I try to assign a value with more than 32 bit,
it fails. To illustrate:

for (i=0; i<64; i++){
long long int k = 1<<i;

cout<<i<<"\t"<<k<<"\t"<<sizeof(k)<<"\n";
}


results in

1 2 8
2 4 8
3 8 8
4 16 8
5 32 8
6 64 8
7 128 8
8 256 8
9 512 8
10 1024 8
11 2048 8
12 4096 8
13 8192 8
14 16384 8
15 32768 8
16 65536 8
17 131072 8
18 262144 8
19 524288 8
20 1048576 8
21 2097152 8
22 4194304 8
23 8388608 8
24 16777216 8
25 33554432 8
26 67108864 8
27 134217728 8
28 268435456 8
29 536870912 8
30 1073741824 8
31 -2147483648 8
32 1 8
33 2 8
34 4 8
35 8 8
36 16 8
......

and so on.

I'm beyond confused - can anyone here help me out? Machine is a Core 2
Duo Macbook Pro with OSX10.5, gcc, Xcode.

Thanks

Oliver
 
C

Captain Trips

Oliver said:
I need a >49 bit integer type. tried sizeof(long long), says 8. 8 byte =
64 bit right? but when I try to assign a value with more than 32 bit,
it fails. To illustrate:

for (i=0; i<64; i++){
long long int k = 1<<i;
unsinged long int k = 1<<i; // use this
cout<<i<<"\t"<<k<<"\t"<<sizeof(k)<<"\n";
}

That happens because you have only half of the numbers for positive, the
other half is used for negatives.

Look here: http://www.cplusplus.com/doc/tutorial/variables.html
 
J

jellybean stonerfish

I need a >49 bit integer type. tried sizeof(long long), says 8. 8 byte =
64 bit right? but when I try to assign a value with more than 32 bit,
it fails. To illustrate:

Maybe your 64 bit "int long long" holds positive and negative numbers.
Is there an "unsigned" type you can use?
 
R

Richard Herring

A. W. said:
1 is an int, so when you shift it left by more than 32 you wrap around.

Worse. When you shift it left by 32 or more, you get UB.

(assuming 'int' is 32 bits on this machine.)

5.8/1:
"The behavior is undefined if the right operand is negative, or
greater than or equal to the length in bits of the promoted left
operand."
The
(int) result fits nicely into a 'long long', so the compiler has no reason
to complain. Try this:

const long long int ONE=1L;

That would be a 'long' literal, not 'long long'.
 
J

Juha Nieminen

Richard said:
Worse. When you shift it left by 32 or more, you get UB.

(assuming 'int' is 32 bits on this machine.)

5.8/1:
"The behavior is undefined if the right operand is negative, or
greater than or equal to the length in bits of the promoted left operand."

That's actually something which should be taken seriously. I remember
back when I was developing on some UltraSparc architecture that if you
shifted an integer by more bits than there was in the integer, the
result would be, IIRC, the original value of that integer (rather than
zero, like AFAIK happens with intel CPUs). In other words, if the amount
of shift was invalid, the UltraSparc would simply not execute it
(leaving the original value of the integer intact). This can come as a
surprise to many.
 
J

James Kanze

Worse. When you shift it left by 32 or more, you get UB.

And it certainly doesn't wrap.

(But am I the only one who absolutely refuses to use shift
operators on signed types.)
(assuming 'int' is 32 bits on this machine.)
5.8/1:
"The behavior is undefined if the right operand is negative, or
greater than or equal to the length in bits of the promoted left
operand."
That would be a 'long' literal, not 'long long'.

But ONE would be an integral constant of type long long.
 
J

James Kanze

That's actually something which should be taken seriously. I
remember back when I was developing on some UltraSparc
architecture that if you shifted an integer by more bits than
there was in the integer, the result would be, IIRC, the
original value of that integer (rather than zero, like AFAIK
happens with intel CPUs). In other words, if the amount of
shift was invalid, the UltraSparc would simply not execute it
(leaving the original value of the integer intact). This can
come as a surprise to many.

I think that on a lot of architectures, i << n will actually
execute as i << (n % B), where B is the number of bits in i. So
that on a 32 bit machine, i << 32 shifts 0, i << 33 shifts 1,
etc.

Of course, if the shift count is a constant, the compiler should
warn.
 
F

farseerfc

that is because i and 1 is not long long, and therefore the result of 1<<i
is not long long, not enough to hold a long long value.
just try this:

long long int i,one=1;
for (i=0; i<64; i++){
long long int k = one<<i;
cout<<i<<"\t"<<k<<"\t"<<sizeof(k)<<"\n";
}
 
S

Stefan Rondinelli

There's no need to use a variable for the constant 1 just to make the
type long long. You can also use a suffix (ll for long long):

long long int i;
for (i=0ll; i<64ll; i++){
long long int k = 1ll << i;
cout<<i<<"\t"<<k<<"\t"<<sizeof(k)<<"\n";
}

----- Original Message -----
From: farseerfc
Date: 26.09.2008 09:26
 
F

farseerfc

;-p, thank you telling me the suffix from
but 1ll seems too much like 111, 1LL should be better

and is the suffix of unsigned long long int ULL? maybe we could write 0ULL
to mean NULL, how beauty C++ is!

Just a joke~
 
O

Oliver Graeser

Victor said:
Try changing this to

long long int k = 1LL << i; // note the suffix after '1'.

You were shifting a simple int (1 is of type int), and its range is more
limited than that of 'long long'.

Indeed this works. Thanks a lot, wasn't aware that directly typed
numbers are always int. Also tried k=100000000000000 but it wouldn't
even compile.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top