Const vs #define

Compare:

const int ITEM_COUNT = 55;
const int MEANING_OF_LIFE = 42;

char buf [ITEM_COUNT];

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

void loop () {}

Compiler:

Binary sketch size: 456 bytes (of a 32256 byte maximum)

Code size:

$ avr-size -C thefilename.elf

AVR Memory Usage
----------------
Device: Unknown

Program:     456 bytes
(.text + .data + .bootloader)

Data:         64 bytes
(.data + .bss + .noinit)

To:

#define ITEM_COUNT 55
#define MEANING_OF_LIFE 42

char buf [ITEM_COUNT];

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

void loop () {}

Compiler:

Binary sketch size: 456 bytes (of a 32256 byte maximum)

Code size:

$ avr-size -C thefilename.elf

AVR Memory Usage
----------------
Device: Unknown

Program:     456 bytes
(.text + .data + .bootloader)

Data:         64 bytes
(.data + .bss + .noinit)

So it's the same.

The use of #define can lead to subtle problems, just as an example:

#define FOO 5
#define ITEM_COUNT FOO + 3

Now ITEM_COUNT should be 8, right? But if you later use:

char buf [ITEM_COUNT * 2];

That will expand to:

char buf [5 + 3 * 2];

So buf will be 11 long, not 16. Proof:

#define FOO 5
#define ITEM_COUNT FOO + 3

char buf [ITEM_COUNT * 2];

void setup () 
{
Serial.begin (115200);
Serial.println ();
Serial.println (sizeof buf);
}

void loop () {}

Output:

11

Also see here:

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7

In short, const identifiers act like they're part of the language because they are part of the language. The preprocessor can be thought of as a language layered on top of C++.

And read this bit:

Are you saying that the preprocessor is evil?

Yes, that's exactly what I'm saying: the preprocessor is evil.