Why use an int variable for a pin when const int, enum or #define makes much more sense

const int led = 13;

That is the correct method. Or even:

const byte led = 13;

How many pins do you have?

Some of the tutorials did not quite go through as much quality control as they might have.

Performance will be better using const byte, compare to int however the compiler may be smart enough to realize what you are doing.

What you can do is gently encourage people to use more efficient techniques by using them in your own code.


Responses to comments

  1. A commenter has suggested that byte is not standard C. This is correct, however this is an Arduino StackExchange site, and I believe using standard types supplied by the Arduino IDE is acceptable.

    In Arduino.h there is this line:

    typedef uint8_t byte;
    

    Note that this is not exactly the same as unsigned char. See uint8_t vs unsigned char and When is uint8_t ≠ unsigned char?.

  2. Another commenter has suggested that using byte will not necessarily improve performance, because numbers smaller than int will be promoted to int (see Integer Promotion Rules if you want more on this).

    However in the context of a const identifier, the compiler will generate efficient code in any case. For example, disassembling "blink" gives this in the original form:

    00000086 <loop>:
      86:   8d e0           ldi r24, 0x0D   ; 13
      88:   61 e0           ldi r22, 0x01   ; 1
      8a:   1b d1           rcall   .+566       ; 0x2c2 <digitalWrite>
    

    In fact it generates the same code whether the 13:

    • Is a literal
    • Is a #define
    • Is a const int
    • Is a const byte

The compiler know when it can fit a number into one register and when it can't. However it is good practice to use coding that indicates your intent. Making it const makes it clear that the number won't change, and making it byte (or uint8_t) makes it clear that you are expecting a small number.


Confusing error messages

Another major reason to avoid #define is the error messages you get if you make a mistake. Consider this "blink" sketch which has an error:

#define LED = 13;

void setup() {
  pinMode(LED, OUTPUT);      // <---- line with error
}

void loop() {
  digitalWrite(LED, HIGH);   // <---- line with error 
  delay(1000);             
  digitalWrite(LED, LOW);    // <---- line with error
  delay(1000);              
}

On the surface it looks OK, but it generates these error messages:

Blink.ino: In function ‘void setup()’:
Blink:4: error: expected primary-expression before ‘=’ token
Blink:4: error: expected primary-expression before ‘,’ token
Blink:4: error: expected `;' before ‘)’ token
Blink.ino: In function ‘void loop()’:
Blink:8: error: expected primary-expression before ‘=’ token
Blink:8: error: expected primary-expression before ‘,’ token
Blink:8: error: expected `;' before ‘)’ token
Blink:10: error: expected primary-expression before ‘=’ token
Blink:10: error: expected primary-expression before ‘,’ token
Blink:10: error: expected `;' before ‘)’ token

You look at the first highlighted line (line 4) and don't even see a "=" symbol. Plus, the line looks fine. Now it's fairly obvious what the problem is here (= 13 is being substituted for LED), but when the line is 400 lines further down in the code, it isn't obvious the problem is with the way LED is defined.

I've seen people fall for this many times (including myself).


As Ignacio has rightly states, it's basically because they don't know better. And they don't know better because the people who taught them (or the resources they used when learning) didn't know better.

Much of the Arduino code and tutorials are written by people who have never had any training in programming and are very much "self taught" from resources by people who themselves are very much self taught with no proper training in programming.

Many of the snippets of tutorial code I see around the place (and especially those that are only available within YouTube videos --- urgh) would be a fail mark if I were marking them in an exam.

Yes, a const is preferred over a non-const, and even over a #define, because:

  • A const (like a #define, unlike a non-const) does not allocate any RAM
  • A const (like a non-const, but unlike a #define) gives the value an explicit type

The second point there is of particular interest. Unless specifically told otherwise with embedded type-casting ((long)3) or a type suffix (3L) or the presence of a decimal point (3.0), a #define of a number will always be an integer and all mathematics performed on that value will be as if it were an integer. Most of the time that's not a problem, but you can run into interesting scenarios when you try to #define a value that is larger than an integer can store, such as #define COUNT 70000 and then perform a mathematical operation with other int values on it. By using a const you get to tell the compiler "This value is to be treated as this variable type" - so you would instead use: const long count = 70000; and all would work as expected.

It also has the knock-on effect that it checks the type when passing the value around the place. Try passing a const long to a function that expects an int and it would complain about narrowing the variable range (or even completely fail to compile depending on the scenario). Do that with a #define and it would just silently carry on giving you the wrong results and leave you scratching your head for hours.


As a 2-week newbie to Arduino I'd pick up on the general idea of Arduino being occupied by non-programmers. Most sketches I have examined, including those on the Arduino site, show a total lack of order, with sketches that do not work & barely a coherent comment in sight. Flow charts are non-existent, and the "Libraries" are an un-moderated jumble.