Use define, const, or enum?

I have to place a number of status flags into a header file. Example:

#define RX_START 1
#define RX_READ 2
#define RX_DONE 3

But I have also seen it done similar to this:

enum read_status {
  RX_START,
  RX_READ,
  RX_DONE
};

And then I have read something about defining a const variable instead of using define.

Which of all of these methods would be the most appropriate and the most efficient in terms of memory requirements on the Arduino?

There was a long, detailed discussion of this a few weeks back

How do I find it? The forum search didn't bring up anything useful, mostly hits for posts that containe "enum" and the other terms in a totally unrelated context.

http://arduino.cc/forum/index.php/topic,86800.0.html

Second search result

AWOL:
http://arduino.cc/forum/index.php/topic,86800.0.html

Great, that explains the const versus define very well.

But what about enum? What is accomplished by using enum instead of multiple const?

const char BLUE = 0;
const char RED = 1;
const char GREEN = 2;

versus

enum colors {
  BLUE,
  RED,
  GREEN
};

And I'd be using it like this:

    switch (get_color()) {
        case BLUE:
            [do something...]
            break;
        case RED;
            [do something else...]
            break;
        case GREEN;
            [do something different...]
            break;
    }

Using a tiny test I created for a different problem, found out that using enum uses more memory. Somewhere I read that enum is an int, is that true? If so, then it would make sense since int is 2 bytes versus char 1 byte. Is it possible to make the enum and uint8_t?

enum state_t {
  high,
  low
};

extern state_t state;

Result: Binary sketch size: 3380 bytes (of a 30720 byte maximum)

#define low    1
#define high   0

extern char state;

Result: Binary sketch size: 3366 bytes (of a 30720 byte maximum)

const char low = 1;
const char high = 0;

extern char state;

Result: Binary sketch size: 3366 bytes (of a 30720 byte maximum)

Somewhere I read that enum is an int, is that true?

Essentially, yes.

Is it possible to make the enum and uint8_t?

You have a two choices...

  • Modify the Arduino IDE so "-fshort-enums" is passed to the compiler. If you choose this option please ask for the changes to be merged.
  • Using your example above, simply change the type of state (extern uint8_t state;). The rest of your code will work unaltered.


Edit: Cosmetic changes.

adilinden:
But what about enum? What is accomplished by using enum instead of multiple const?

const char BLUE = 0;

const char RED = 1;
const char GREEN = 2;




versus


enum colors {
  BLUE,
  RED,
  GREEN
};

In the enum case, you don't have to say what the values should be -- although you can, if you want. With a const, you have to say the value. If you don't care what the values are, then enum may be more appropriate.

In the case of const, it is possible to take the address of the symbol. eg, it is possible to do this:

const char BLUE = 0;
  :
  :
const char *foobar = &BLUE;

With an enum version of BLUE, you will get an error.

As with most things, there are 3 or more ways to skin any particular cat, and in many cases, no single right way, nor even a single way that is generally accepted as best.

As an old-school guy, I always use #define, and that is still a very commonly seen idiom for any constant requirements.

gardner:
As an old-school guy, I always use #define, and that is still a very commonly seen idiom for any constant requirements.

Well, to me a variable is just that, a container to hold value that is changed by the program. As such I would expect it to be stored in RAM. A #define to me is like a macro, something the compiler replaces with the value, something that is defined once and cannot be changed during program execution.

Personally I prefer #define. But then I am learning a lot and I am not adverse to doing things in a different way of it is beneficial.

I changed it to extern uint8_t state;. The result is 3366 bytes, so no difference in code size between using enum, const or define. I suppose it then comes down to preference, readability, etc...

Thank you!

I came accross this topic, here is the answer using the updated IDE (1.0.5)

// Compiled each of these separately
// define = 472 bytes
/*
#define ITEM_COUNT 55
#define MEANING_OF_LIFE 42
#define HIDDEN 10
*/

// const = 472 bytes
/*
const uint8_t ITEM_COUNT = 55;
const uint8_t MEANING_OF_LIFE = 42;
const uint8_t HIDDEN = 10;
*/

// enum = 472 bytes
enum stuff{
  ITEM_COUNT = 55,
  MEANING_OF_LIFE = 42,
  HIDDEN = 10,
};


char buf [ITEM_COUNT];

void setup () 
{
  buf [5] = MEANING_OF_LIFE;
}

void loop () {}

It seems that const, enum, and define all do the same thing -- if the variable is unused, the compiler doesn't use it. Also, they take up the same amount of memory.

One advantage of const or #DEFINE over enum is that the value of the parameter can be overloaded to have some use. For example, I had a program with a state-tracking variable, and LEDs that changed to indicate state. I set it up like this:

const byte led1pin = 5;
const byte led2pin = 6;
const byte led3pin = 7;

const byte stateOne = led1pin;
const byte stateTwo = led2pin;
const byte stateThree = led3pin;

byte currentState;

That way I could do something like this:

void updateLEDstate()
{
  // turn off all LEDs
  digitalWrite(led1pin, LOW);
  digitalWrite(led2pin, LOW);
  digitalWrite(led3pin, LOW);

  // turn on LED corresponding to current behavior state
  digitalWrite(currentState, HIGH);
}

This avoids needing a switch(currentState) construct.

It's an old post, but I came across this and was surprised that no one suggested doing this:

enum Color: byte
{
   RED, GREEN, BLUE
};

This of course is C++, not C.

Also, the post above doesn't make any sense at all but this thread is too old to get into that.

Conclusion: use enums, they're handy.