Still learning bit manipulations, so sorry for not understanding...My question is how do I get my "packed" data back from using something like:
My question is now how do I extract the cardColor, cardType, showFace, and reserved values back from the variable card?!
cardface = (card >> 8) & 0xFF;
cardcolor = (card >> 24) & 0xFF:
wouldn't that work?
Thanks for the fast response! I got it to work with:
char reserved = (card >> 0 ) & 0xFF; char showFace = (card >> 8 ) & 0xFF; char value = ( card >> 16 ) & 0xFF; char color = ( card >> 24 ) & 0xFF;
If you don't care, what is the &0xFF for? I don't know why this stuff confuses me at times.
The 0xFF masks off the stuff "above" the desired value, i.e. cardface = (card >> 8) would still have cardcolor in it.
Oh, okay! Thanks a million!
If you don't care, what is the &0xFF for? I don't know why this stuff confuses me at times. 
& 0xFF => "Truncate to only the last 8 bits".
1 AND 1 == 1
1 AND 0 == 0
0 AND 1 == 0
0 AND 0 == 0
So say you have 0x5559DF50 & 0xFF. The AND is done bit-for-bit, so
01010101010110011101111101011001 (0x5559DF59) & 00000000000000000000000011111111 (0xFF) = 00000000000000000000000001011001 (0x00000059)
Is it considered clean to use an enum like that? I mean, it's practically deprecated in C++. Perhaps any of you code gods or monkeys could enlighten me please.
It might not be entirely clean, but it is handy. And enums will always cast down to ints.
In one of my projects I use them for bit flags, which means I can't actually use the enum type to store the final values, so any place the enum is used, I just pass ints around.
Enums are deprecated in C++? WTF?
Only on Tuesdays. Since us indie developers code on weekends and take Tuesday off, we never heard about it.
Treating it like a list of int's that starts at 0 is... isn't it?
Not to my knowledge.
It is true though that enums and ints are different types in C++, and converting between them is subject to the same rules as every other cast.
Since an enums underlying type is int, every possible value of any given enum can be converted to int without loss of precision. The reverse is not true, though, because most enums do not define values for the entire possible range of integers (and in fact, they never can, because the size of an integer may vary between platforms and is usually larger than the minimum size mandated by the language standard). Hence, casting from enum to int is a widening cast, which may be done implicitly, but casting from int to enum is narrowing and needs to be explicit. It can also fail, and you must be prepared to handle (or prevent) this.
Consequently, the following operations are all OK:
- assigning enum to int
- comparing enum vs. int
- using enum as array index
- passing enum as int argument
- using enum as case label in a switch
- performing bit-wise logic with enums, as long as the result is assigned to an int, not an enum
Which covers most, but not all, cases that may arise when you use an enum to define integer constants.
An enum is still tremendously handy for a list of integer constants, mainly because:
it is evident at a glance that the constants belong together
by using the enum type for function arguments, you can force only valid values to be passed, even if you later assign them to an int internally
you don't need to keep track of which values are used for what (although you can), because enums auto-number by default
It can also fail, and you must be prepared to handle (or prevent) this.
by using the enum type for function arguments, you can force only valid values to be passed, even if you later assign them to an int internally
bamccaig@castopulence:~/src$ cat main.cpp
#include <iostream>
enum Example
{
ZERO,
ONE,
TWO
};
void printExample(Example);
int main(int argc, char * argv[])
{
Example e;
unsigned long long l = -1;
std::cout << "Example{"
<< ZERO << ", "
<< ONE << ", "
<< TWO
<< "}"
<< std::endl;
std::cout << "l=" << l << std::endl;
e = (Example)5;
printExample(e);
e = (Example)l;
printExample(e);
printExample((Example)0xdeadbeef);
return 0;
}
void printExample(Example e)
{
std::cout << "e=" << e << std::endl;
}
bamccaig@castopulence:~/src$ g++ -Wall main.cpp
bamccaig@castopulence:~/src$ ./a.out
Example{0, 1, 2}
l=18446744073709551615
e=5
e=-1
e=-559038737
bamccaig@castopulence:~/src$
Hmmm... OK, suppose that first point is moot.
The second point I should probably rephrase as "by using the enum type for function arguments, you can strongly suggest a range of valid values to the using code, even if you later assign them to an int internally". While you can pass integer values into a function through an enum argument, you need to use an explicit cast to do so, and, assuming you have at least half a brain, this should flash an alarm bell and tell you that it's probably a very good idea to first check if the cast is actually valid, or better yet, if you shouldn't be storing the value as the correct enum type in the first place.