EDIT: microtherion ger ett utmärkt svar som korrigerar några av mina punkter här, särskilt om minnesanvändning.
Som du har identifierat finns det vissa situationer där du tvingas använda en #define
, eftersom kompilatorn inte tillåter en const
-variabel. På samma sätt tvingas du i vissa situationer använda variabler, till exempel när du behöver en rad värden (dvs. du kan inte ha en array med #define
).
Det finns dock många andra situationer där det inte nödvändigtvis finns ett enda "rätt" svar. Här är några riktlinjer som jag skulle följa:
Typsäkerhet
Ur en allmän programmeringssynpunkt är const
variabler vanligtvis att föredra (om möjligt). Den främsta anledningen till detta är typsäkerhet.
En #definiera (förprocessormakro) kopierar bokstavligen värdet direkt till varje plats i koden, vilket gör varje användning oberoende. Detta kan hypotetiskt leda till tvetydigheter, eftersom typen kan komma att lösas annorlunda beroende på hur / var den används.
En const
-variabel är bara någonsin en typ, som bestäms genom sin förklaring och löstes under initialiseringen. Det kommer ofta att kräva en uttrycklig rollbesättning innan den kommer att bete sig annorlunda (även om det finns olika situationer där det säkert kan implicit typfrämjas). Åtminstone kan kompilatorn (om den är korrekt konfigurerad) avge en mer tillförlitlig varning när ett typproblem uppstår.
En möjlig lösning för detta är att inkludera en explicit cast eller ett typsuffix i en #definiera . Till exempel:
#define THE_ANSWER (int8_t) 42 # define NOT_QUITE_PI 3.14f
Det tillvägagångssättet kan dock i vissa fall orsaka syntaxproblem, beroende på hur den används.
Minnesanvändning
Till skillnad från allmänna datorer är minnet uppenbarligen till en premie när man arbetar med något som en Arduino. Att använda en const
-variabel jämfört med en #define
kan påverka var data lagras i minnet, vilket kan tvinga dig att använda den ena eller den andra.
-
const
-variabler lagras (vanligtvis) i SRAM, tillsammans med alla andra variabler. - Bokstavsvärden som används i
#define
kommer ofta lagras i programutrymmet (Flash-minne), tillsammans med själva skissen.
(Observera att det finns olika saker som kan påverka exakt hur och var något lagras, till exempel kompilator konfiguration och optimering.)
SRAM och Flash har olika begränsningar (t.ex. 2 KB respektive 32 KB för Uno). För vissa applikationer är det ganska enkelt att ta slut på SRAM, så det kan vara till hjälp att flytta vissa saker till Flash. Det omvända är också möjligt, även om det troligen är mindre vanligt.
PROGMEM
Det är möjligt att få fördelarna med typsäkerhet samtidigt som man lagrar data i programutrymme (Flash) . Detta görs med nyckelordet PROGMEM
. Det fungerar inte för alla typer, men det används vanligtvis för matriser med heltal eller strängar.
Det allmänna formuläret i dokumentationen är som följer:
dataType variableName [] PROGMEM = {dataInt0, dataInt1, dataInt3 ...};
Strängtabeller är lite mer komplicerade, men dokumentationen har fullständiga detaljer.