Reputation: 947
Let's say I have an enum that only contains values up to 0xFF. I want to place that enum value into a byte variable. AFAIK enums are int
s underneath (vxWorks). The machine I am coding for is big endian. I don't understand if this matters when I want to place it into a uint8_t. Which of these options will work and which is the best?
typedef enum {
kEnum1 = 0x00,
kEnum2 = 0x01,
kEnum3 = 0xFF
} MyEnum;
MyEnum myenum = kEnum3;
uint8_t mybyte = 0;
// option 1, do nothing
mybyte = myenum ;
// option 2, explicit cast
mybyte = (uint8_t)myenum;
// option 3, use operators
mybyte = (myenum & 0xFF000000) >> 24;
When I test this on an online compiler, which I assume is little endian, option 3 of course does not work. But the others do. I just don't understand how big endian machines will treat these options.
Upvotes: 0
Views: 159
Reputation: 224310
A cast converts a value to a new type. C 2018 6.5.4 5 says “Preceding an expression by a parenthesized type name converts the value of the expression to the unqualified version of the named type…” So if an expression of enumeration type has value 255 (0xFF
), then converting it to uint8_t
produces the value 255 as a value of type uint8_t
. This is true for any arithmetic value that is representable in the destination type. (If the value is not representable, then there can be various results, including wrapping, trapping, undefined behavior, and truncation, depending on the types involved.)
In more detail, C 2018 specifies the results of conversions between integer types in 6.3.1.3, and an enumeration type is an integer (C 2018 6.2.5 16: “An enumeration comprises a set of named integer constant values…”). 6.3.1.3 1 says “When a value with integer type is converted to another integer type other than _Bool
, if the value can be represented by the new type, it is unchanged.”
The bytes used to represent an enumeration or other object are not relevant to casts, because the results of casts are specified by values, not representations.
Upvotes: 5
Reputation: 225212
All of your examples will work the same regardless of endianness. That is, options 1 and 2 will work fine, and option 3 won't. You can fix option 3 like:
mybyte = myenum & 0xFF;
If you want one that would break, try this one, which actually addresses the underlying memory rather than using operators:
mybyte = *(uint8_t *)&myenum;
As far as which is the best, option 1 and 2 are 100% equivalent. If you want to be extra careful, just check that myenum
isn't outside of the range of a uint8_t
before doing the assignment.
Upvotes: 0