Page 1 of 1
long long/uint64_t acting... weird (c++)
Posted: Wed Sep 05, 2007 9:50 pm
by Zacariaz
basicly i can assign any value (allthough with warnings) i choose directly to the 64 bit integer but when using bitwise operators its acting strange:
Code: Select all
std::cout << sizeof(unsigned long long); /* outputs 8, which is correct */
unsigned long long test = 0;
test |= 1 << 30; /* test now contains the value 1,073,741,824 which is correct */
test |= 1 << 31; /* test now contains the value 18,446,744,071,562,067,968 when it should contain 3,221,225,472 */
test = 3221225472; /* test now contains the value 3,221,225,472 as it should, however the compiler gives a warning: "[Warning] this decimal constant is unsigned only in ISO C90" */
I dont supose there is anything that can be done as long as im running a 32 bit OS?
Posted: Wed Sep 05, 2007 10:47 pm
by Colonel Kernel
Try putting "ULL" after your integer constants.
Think about what's happening with test |= 1 << 31; step-by-step. First, the right hand side (1 << 31) is evaluated. At this point, the compiler only sees literal integers and the << operator -- it has no clue as to the type of the expression other than the literals, which have no special suffixes... Therefore it will default the type to "int". Before evaluating |=, the type of the right-hand expression must be converted from "int" to "unsigned long long", which results in automatic sign-extension. That's why you're getting such a huge number -- because the number you're ending up with is probably 0xFFFFFFFF80000000.
The compiler is only doing what you told it to do. Be careful!
Posted: Thu Sep 06, 2007 6:59 am
by Zacariaz
Code: Select all
#include <iostream>
int main() {
unsigned long long test = 0;
for(char i = 0; i < 64; i++) {
test |= 1ULL << i;
std::cout << test << std::endl;
}
for(char i = 63; i > 0; i--) {
test -= 1ULL << i;
std::cout << test << std::endl;
}
}
This little example works, im happy to say, but did i catch it all? Its kinda important i dont miss anything, as i will be using ull's alot and allso doing bitwise manipulation to them alot (butboard stuff)
Anyway, thanks!
Posted: Thu Sep 06, 2007 7:26 am
by Solar
Yes, you did catch it all.
It's easy: In olden C, if you didn't declare a variable, it was int by default. Otherwise, your definition specifies the width of the variable.
Same with numeric constants. Unless defined to a certain width, they are int, otherwise your definition... you get the idea.
So that leaves the 0, the 64 and the 63 as constants. The first casts to ULL just fine, the other two are loop counters that have nothing to do with 64bit.
Erm... I think that should be a 64 in the second loop too, though.
Posted: Thu Sep 06, 2007 7:40 am
by Zacariaz
Solar wrote:The first casts to ULL just fine, the other two are loop counters that have nothing to do with 64bit.
Im not quite sure what you mean. Did i cast ull anywhere not needed?
Solar wrote:Erm... I think that should be a 64 in the second loop too, though.
Yes, if i wanted the last printout to be 0, but then in order to achive perfection i would have to make the first out be 0 as well, but that would lieve an imperfect looking code with cout's outside the loops! cant have that
Posted: Thu Sep 06, 2007 7:58 pm
by Zacariaz
One last question...
Code: Select all
#include <iostream>
#include <bitset>
int main() {
std::bitset<64> test;
test = 0xffffffffffffffffull;
std::cout << test;
}
output = 0000000000000000000000000000000011111111111111111111111111111111
Yes it is a looong stream of bits, however the problem is obious. Only 32 bits of the 64 is assigned to the bitset.
Is there anything that can be done about that?
Posted: Fri Sep 07, 2007 3:12 am
by Combuster
I would think about overloading the assignment operator for (unsigned) long longs
Posted: Fri Sep 07, 2007 3:45 am
by Solar
Is that actually operator=() called there, or the bitset( unsigned long ) constructor? Anyway, the point is valid: As C++ doesn't know about unsigned long long, it isn't taken into account "automagically".