Besser bool oder uint8_t für binäre Statusinformation ?

Gast #5276078
Lesenswert?

Hallo Mikrocontrollergemeinde,

Ich programmiere MCUs in C und habe mir schon oft folgende Frage 
gestellt :

Ist es besser bool zu benutzen,  oder uint8_t um binäre 
Statusinformation zu Speichern oder Zurückzugeben? (Siehe kleines 
Beispiel)

1
 
2
//Lösung A: 
3
static inline bool EndPosition (void){
4
  return (bool)PINA&(1<<0);    //PINA0 - End position switch
5

6
//Lösung B:
7
static inline uint8_t EndPosition (void){
8
  return PINA&(1<<0);    //PINA0 - End position switch
9
}
10

11
int main()
12
{
13
  .
14
  ...
15
  while(!EndPosition)
16
  {
17
  StepperDrive();
18
  };
19
  
20
  ..
21
  .


Welches ist zu bevorzugen ?
Lösung A oder Lösung B ?

Ich vermute beides erzeugt den gleichen Maschinencode (Ich habe es aber 
nicht geprüft).
Gibt es Aspekte unter welchen Lösung A oder Lösung B besser ist?
Oder ist es wirklich egal?

Grüße und Danke im Voraus für Eure Antworten.

Jan
Gast #5276096
Lesenswert?

bool ist normalerweise vom typ int. und dieser Typ ist in c für diesen 
Prozessor der Default-Typ, in der Regel der schnellste.

Bei einem reinen 8-Bitter könnte bool jedoch Performance kosten.
Zudem kann 16 oder 32 Bit für eine binäre Info RAM kosten.

Dein Code ist zwar richtig (die Funktionen liefern 0 oder 1 zurück), der 
Quelltext sagt aber, dass es nur zufällig so ist.

Hättest Du ein Höherwertiges Bit getestet, so wäre der Rückgabewert 2, 4 
oder was auch immer. Das ist auch OK, nur ist der Rückgabewert dann 
strenggenommen nicht bool (0/1), sondern 0/!=0.
1
static inline bool EndPosition (void){
2
  return 0!=(PINA&(1<<3));    //PINA3 - End position Switch
3
}
oder einfach doppelt negieren
1
static inline bool EndPosition (void){
2
  return !!(PINA&(1<<3)); 
3
}
(Firma: SEGGER) #5276103
Lesenswert?

Lösung C wenn es um Effizienz geht ;-)

Bei den meisten Calling Conventions wird der Return Wert einer Funktion 
in einem CPU Register zurückgegeben. Am effizientesten ist es, wenn die 
Variablenbreite des Return Wertes der Breite des Registers entspricht.

Also sagen wir du hast eine 8 Bit CPU mit 8 Bit breiten Registern und 
möchtest eine long zurückgeben. Das passt dann nicht mehr in ein 
Register, also ineffizient. Genauso wenn du eine 32 Bit CPU hast und 
einen 8 Bit Wert zurückgeben möchtest. Das passt zwar rein aber 
anschließend muss evtl. noch maskiert werden.
Bei den meisten CPU/Compiler Kombinationen entspricht der "int" Datentyp 
der CPU Registerbreite. Das gilt aber natürlich nur für 16/32 Bit CPUs. 
Bei einer 8 Bit CPU würdest du "char" nehmen. Aber Vorsicht, auch hier 
gibt es Ausnahmen, ich erinnere mich an den Renesas H8 und den Renesas 
Compiler. Der H8 ist eine 32 Bit CPU ist, aber ein "int" war nur 16 Bit 
groß.

Bei dir müsstest du schauen, wie bool implementiert ist. Es kann sein, 
dass es das gleiche wie uint8_t ist. Dann würde ich bool nehmen, wenn 
die Funktion eine true/false Wert zurückliefert und nicht einen Wert 
zwischen 0..255. Ich würde die Funktion dann aber auch 
IsEndPositionReached() oder so nennen.
Gast #5276293
Lesenswert?

Vielen Dank für die Zahlreichen Antworten.

Ich denke auch A ist die bessere Variante.
Vielleicht könnte man verallgemeinern das der gewählte Variablentyp 
immer dem Datentyp entsprechen sollte.
In diesem Fall möchte man einen „true“ oder „false“ zurückgeben, also 
ist bool die Richtige Wahl.

Til S. schrieb:
> Lösung C wenn es um Effizienz geht ;-)

Ist es tatsächlich so, dass die Lösung A unter Umständen nicht die 
effizienteste Lösung ist?
(Bei Verwendung moderner C-compiler.)
Ich dachte das durch das inlinen,  Lösung A immer die effizienteste 
Variante ist.

Volker SK schrieb :
> Warum nicht einfach:
> #define EndPosition PINA0

Funktionen sind Makros vorzuziehen.
Bei Makrofunktionen geht die Type-überprüfung verloren.


Gruss,
Jan
Gast #5276315
Lesenswert?

Lösung C ;-)
1
typedef enum {
2
  UNBEKANNT, AM_ENDE, UNTERWEGS
3
} Position;
4

5
Position wo_bin_ich(void)
6
{
7
  Position pos = UNBEKANNT;
8

9
  if(PINA&(1<<0)
10
    pos = UNTERWEGS;
11
  else if ...
12
    pos = AM_ENDE;
13
  
14
  return pos;
15
}
16

17
main()
18
{
19
  ...
20
  if(wo_bin_ich() == UNTERWEGS)
21
  {
22
     Stepper();
23
  }
24
  ...
25
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren