pbuzz007
pbuzz007

Reputation: 947

Does endianess matter when casting

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 ints 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

Answers (2)

Eric Postpischil
Eric Postpischil

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

Carl Norum
Carl Norum

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

Related Questions