Arduino: const vs #define

Longe vão os tempos em que os computadores possuíam quantidades irrisórias de memória RAM quando comparadas com os dias de hoje. Falo sim em quantidades na ordem dos kbytes de memória.

Actualmente os programadores descuram um pouco essa afinação e optimização na alocação de memória das suas aplicações, mas ainda existe um pequeno grupo onde ainda é necessário optimizar ao pormenor a alocação de memória, refiro-me então às áreas da robótica e electrónica, de um modo geral na utilização de micro-controladores.

#define

De uma forma simples podemos dizer que o #define é uma directiva do pré-processador do compilador que de certo modo torna mais simples a definição de uma variável estática que será usada múltiplas vezes, ou seja, no caso de ser necessário alterar o valor dessa mesma variável estática basta mudar o valor do #define ao invés de andar a alterar todas as variáveis ao longo do código.

Por exemplo:

#define Pin 10

void setup()
{
  pinMode(Pin, OUTPUT);
}

void loop() 
{
  digitalWrite(Pin, HIGH);
  delay(500);
  digitalWrite(Pin, LOW); 
  delay(500);
}

O que realmente acontece ao compilar o código acima é o seguinte:

#define Pin 10

void setup() 
{
  pinMode(10, OUTPUT);
}

void loop() 
{
  digitalWrite(10, HIGH);
  delay(500);
  digitalWrite(10, LOW); 
  delay(500);
}

A utilização do #define é uma funcionalidade muito útil e poderosa, não havendo na realidade perdas de performance quando comparado com a definição de uma variável do tipo inteiro para definir o Pin.

Compilando o programa usando o #define obtenho:

Arduino: usando o define

#const

De uma forma geral o que o modificador #const faz é “dizer” ao compilador que a variável (ou ponteiro) não pode ser alterado no decorrer do código. No entanto continua a ser uma variável e dependendo de onde seja usada pode ou não consumir memória RAM.

Mas como o IDE usado pelo Arduino e seu compilador avr-gcc é inteligente o suficiente para saber que uma variável precedida pelo modificador #const não pode ser alterada dentro do programa activo este irá tentar deixá-la fora da memória RAM.

Pegando do exemplo dado anteriormente e usando o modificador #const o código ficaria assim:

#const int Pin = 10;

void setup()
{
  pinMode(Pin, OUTPUT);
}

void loop() 
{
  digitalWrite(Pin, HIGH);
  delay(500);
  digitalWrite(Pin, LOW); 
  delay(500);
}

O que realmente acontece ao compilar o código acima é o seguinte:

#const int Pin = 10;

void setup()
{
  pinMode(10, OUTPUT);
}

void loop() 
{
  digitalWrite(Pin, HIGH);
  delay(500);
  digitalWrite(Pin, LOW); 
  delay(500);
}

Mas será que a utilização do modificador #const irá consumir mais ou menos memória RAM que o modificador #define?

 Compilando o programa usando o #const obtenho:

Arduino: usando const

O que é certo é que nenhum dos casos consome qualquer memória RAM, mas não se deixem enganar pelo valor Binary sketch size: 1.076 bytes apresentado pelo IDE do Arduino, pois esse valor refere-se ao HEX file do código e não tem uma relação directa com a memória RAM utilizada na realidade.

Para averiguarmos com exactidão a quantidade de memória RAM ocupada podemos usar a ferramenta AVR-SIZE disponibilizada pelo IDE do Arduino.

Publicado na edição 44 (PDF) da Revista PROGRAMAR.