nouser2013
nouser2013

Reputation: 666

How to Iterate only directly set enum values in plain c?

I have an enum defined in plain c like so:

typedef enum {
    // Determine position of Red and Green color:
    // RED[2:0], GREEN[5:3], BLUE implicitly. Thus, [7:6]==!0
    LED_BO_RedGreenBlue=0b00010001,
    LED_BO_RedBlueGreen=0b00100001,
    LED_BO_GreenBlueRed=0b00001100,
    LED_BO_GreenRedBlue=0b00001010,
    LED_BO_BlueRedGreen=0b00100010,
    LED_BO_BlueGreenRed=0b00010100,
} led_byteorder_values_t;

Unfortuantely, the only way I have come up with to check if a given uint8_t has a value defined explicitly in this enum is this:

uint8_t byteToTest = 0; // has invalid value, so /default/ path will be taken.
switch (byteToTest) {
    case: LED_BO_RedGreenBlue: break;
    case: LED_BO_RedBlueGreen: break;
    case: LED_BO_GreenBlueRed: break;
    case: LED_BO_GreenRedBlue: break;
    case: LED_BO_BlueRedGreen: break;
    case: LED_BO_BlueGreenRed: break;
    default: byteToTest = LED_BO_RedGreenBlue; break;
}

Is there a better / shorter way to test a variable against arbitrary values, possibly without having to define an additional const [...]?

Upvotes: 4

Views: 1005

Answers (2)

WhozCraig
WhozCraig

Reputation: 66234

Though the attractiveness of the following alternative isn't heartwarming, it is none-the-less likely effective for the platform you're currently using.

The language doesn't support enumeration of enum values as a built-in construct. There are ways to "fake" it though. Once such way is by providing your own table-of-enum, then enumerating that. I will argue, however, whether this is "better". Easier to type, yes. Logical, maybe. but your switch statement is most-assuredly going to compile down to more efficient code. I would be shocked if it didn't.

typedef enum {
    // Determine position of Red and Green color:
    // RED[2:0], GREEN[5:3], BLUE implicitly. Thus, [7:6]==!0
    LED_BO_RedGreenBlue=0b00010001,
    LED_BO_RedBlueGreen=0b00100001,
    LED_BO_GreenBlueRed=0b00001100,
    LED_BO_GreenRedBlue=0b00001010,
    LED_BO_BlueRedGreen=0b00100010,
    LED_BO_BlueGreenRed=0b00010100,
} led_byteorder_values_t;

static const led_byteorder_values_t led_byteorder_values[] = 
{
    LED_BO_RedGreenBlue,
    LED_BO_RedBlueGreen,
    LED_BO_GreenBlueRed,
    LED_BO_GreenRedBlue,
    LED_BO_BlueRedGreen,
    LED_BO_BlueGreenRed
};

static const size_t size_led_byteorder_values = 
    sizeof(led_byteorder_values)/sizeof(*led_byteorder_values);

With that you can enumerate the values directly via a [0...size_led_byteorder_values) loop. you can still custom-order the loop by adjusting the table entry order for most-to-least-likely hit for quicker loop-exit. But again, it isn't like that isn't possible with a decently formed switch such as yours.

Anyway, its a thought, and I feel your pain. Its one of the few features that not-just-C++, but most languages don't offer, and it certainly seems to pop up as useful once in awhile.

Best of luck.

Upvotes: 4

Mani
Mani

Reputation: 17595

You may define enum like below.

typedef enum : uint8_t { // see this type, it's a better defintion
    // Determine position of Red and Green color:
    // RED[2:0], GREEN[5:3], BLUE implicitly. Thus, [7:6]==!0
    LED_BO_RedGreenBlue=0b00010001,
    ........

} led_byteorder_values_t;

Upvotes: 0

Related Questions