I'm exchanging packets with an embedded device and I'd really like to be able to use enums in the sub-byte parts of the packet definitions too. But I can't guess a syntax that might work and I suspect it's not possible, since I can't work out how to declare a partial-byte subtype in C++:
enum class communication_path_t : uint8_t { Ethernet = 0, Wifi = 1 }; typedef struct { communication_path_t pathByte; // works, uses one byte // ... // single byte split three ways uint8_t retryCount : 3; communication_path_t path : 3; // compile error uint8_t deviceType : 2; } packet_t;
That doesn't compile, because you can't fit an 8 bit enum into a 3 bit field. Edited in the exact error:
<anonymous struct>::path’ is too small to hold all values of ‘enum class MyNamespace::communication_path_t’ [-Werror]
What I'd like to do is something like this:
enum class communication_path_t : uint8_t : 3 { ...
or
typedef uint8_t:3 three_bit_int_t; enum class communication_path_t : three_bit_int_t { ...
Neither of those compile, and I'm having trouble finding documentation that refers to both bit fields and enums, making me suspect there is none. Before I spend hours looking, is what I'm trying to do even possible?
Edit: upgrading to g++-4.9 does not fix the problem. It's remarkably painless, just:
sudo apt-get install g++-4.9 g++-4.9 --version g++-4.9 (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2 GCC 4.9.2 released [2014-10-30]
Then change my build chain to use "g++-4.9" instead of "g++". Unfortunately I get the same error:
g++-4.9 -Dlinux -std=c++11 -pthread (...) ../common/LogPacketBreakdown.cpp In file included from ../common/LogPacketBreakdown.cpp:12:0: ../common/PacketInfo.h:104:50: error: ‘Digiflex::<anonymous struct>::communicationPath’ is too small to hold all values of ‘enum class Digiflex::communication_path_t’ [-Werror] communication_path_t communicationPath : 3;
Looks as though I need 5.0 and that's not in the Ubuntu experimental tools list so I'd need to build from source. I think I'll just live with the workaround for now. Thanks all for your help.
On an 8-bit processor, enums can be 16-bits wide. On a 32-bit processor they can be 32-bits wide or more or less. The GCC C compiler will allocate enough memory for an enum to hold any of the values that you have declared. So, if your code only uses values below 256, your enum should be 8 bits wide.
For C++ and relaxed C89/C99/C11, the compiler allows enumeration constants up to the largest integral type (64 bits).
In C language, an enum is guaranteed to be of size of an int . There is a compile time option ( -fshort-enums ) to make it as short (This is mainly useful in case the values are not more than 64K). There is no compile time option to increase its size to 64 bit.
The size is four bytes because the enum is stored as an int . With only 12 values, you really only need 4 bits, but 32 bit machines process 32 bit quantities more efficiently than smaller quantities.
The code you posted should be accepted by the most recent compilers. You can see this bug report where the fix should have occurred: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242
In today's gcc, a warning should still be emitted. In clang, you should see nothing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With