Följande
kommer att utföras på ett konstant sätt:
Kod: Markera allt
#define PINB 0x1234
#define PB7 7
if(!(PINB & (1<<PB7)))
Om kompilern kommer att skifta en '1' 7 gg under programkörningen ska den kompiler inte användas alls!
Detta kommer att utföras som:
if(!(PINB & 0x80))
Men
Kod: Markera allt
#define PINB 0x1234
unsigned char PB7;
PB7 = 7;
if(!(PINB & (1<<PB7)))
kommer att bli en del kod där den rent faktisk shiftar bit'en innan andningen.
Vad en del personer gör av fel är t.ex.
Kod: Markera allt
#define PINB 0x1234
#define PB7 7
if((PINB & (1<<PB7)) == 1)
Själva if()-satsen kan mycket gå väl eller fel, helt utan att kompilern gör fel! Och allt beror på brist på kunnighet i C.
Förklaring:
PINB & 0x80 kan ge 0x00 eller 0x80 som svar, inget annat. Vissa µC medger bit-adressering och då kan man testa en viss bit som '0' eller '1' men i en del fall medför detta att kompilern rent faktisk kollar om 0x00 eller 0x080 är lika med 0x01 (vilket det aldrig är) och i andra fall kan kompilern shifta bits i svaret så att en jämförelse kan fungera. Ingen av sätten är fel, osäkerheten beror på programmörens fel.
Lösningen är att sluta göra bort sig och istället använda sig av C-standardens definition:
* Allt annat än falskt är sant.
* 0x00 är alltid falskt. Alltså är allt icke-noll sant.
Så i detta exempel görs det helt korrekt:
if(!(PINB & (1<<PB7)))
Det kan översättas till: Om innehållet i minnet som PINB pekar på AND'ad med 0x80 ICKE är sant, utför då ...