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?
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!
Top three reasons why my OS project died:
Too much overtime at work
Got married
My brain got stuck in an infinite loop while trying to design the memory manager
#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)
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.
Every good solution is obvious once you've found it.
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
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?
I would think about overloading the assignment operator for (unsigned) long longs
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
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".
Every good solution is obvious once you've found it.