Forum: Compiler & IDEs bool: Größe bei arm-none-eabi c/c++


von Grrr! (Gast)


Lesenswert?

Irgendwie habe ich mich gerade schwindelig gelesen:
Auf 32 bit macht es Sinn, für viele Sachen einen 32 bit int oder uint zu 
nehmen, auch wenn vom Wertebereich z.B. 8 bit reichen würden. Dann muß 
vom Compiler nichts hin- und herschieben und maskieren beim Zugriff. 
Also Geschwindigkeit auf Kosten des Speicherbedarfs. Auch Stichwort 
uint8_fast_t.
Habe ich soweit verstanden.

Wie sieht es jetzt mit bool bei arm-none-eabi- aus? Da habe ich jetzt 
praktisch sämtliche mögliche Varianten gelesen und weiß es nicht. Klar 
kann man, um sicher zu sein, mit uint32_t statt bool arbeiten. Aber das 
ist doch vom Codeverständnis her sch...
Soll man sich also am besten selbst per
1
const uint32_t true = 1U
2
und
3
const uint32_t false = 0U

oder
1
#define TRUE 0x00000001U
2
und
3
#define FALSE 0x00000000U
selber was basteln?

Wahrscheinlich noch was ganz anderes, aber für heute bin ich wohl 
"satt".

von Frank _. (fbi)


Lesenswert?

Schau doch einfach mit "sizeof(bool)" nach, wie Dein Compiler das 
implementiert.
Ich würde bool einfach verwenden wie es ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Grrr! schrieb:

> Wie sieht es jetzt mit bool bei arm-none-eabi- aus? Da habe ich jetzt
> praktisch sämtliche mögliche Varianten gelesen und weiß es nicht. Klar
> kann man, um sicher zu sein, mit uint32_t statt bool arbeiten. Aber das
> ist doch vom Codeverständnis her sch...

Ist es.

bool ist ein Aufzählungstyp, der erst einmal nur ein Byte braucht. Wenn 
du das tatsächlich irgendwo speicherst, verplemperst du daher keine 
unnützen Platz.

Solange der Compiler allerdings den Einsatzbereich der entsprechenden 
Variablen überschauen kann und er im Register gehalten wird, wird der 
Compiler natürlich ein ganzes 32-bit-Register benutzen und muss auch 
keine Bytezugriffe benutzen.

Außerdem kann dieser Typ nur die Werte 0 und 1 annehmen. Wenn du 
irgendeinen anderen Wert zuweist, wird er (durch implizite 
Typumwandlung) bereits bei der Umwandlung in 0 oder 1 gewandelt. Wenn du 
jetzt sowas (wenig sinnvoll, nur als Beispiel) schreibst:
1
bool foo;
2
3
int something(void) {
4
  return foo * 42;
5
}

dann wird zwar für den externen Zugriff auf "foo" ein ldrb codiert (lade 
Byte mit sign extension), aber danach direkt mit 42 multipliziert ohne 
noch irgendwie explizit auf 0 oder 1 zu testen.
1
#define TRUE 0x00000001U
2
und
3
#define FALSE 0x00000000U

Was sollen die 0x und die vielen Nullen überhaupt bewirken?

0x000000000000000 ist die gleiche Zahl wie 0x0 oder einfach nur 0. Wir 
sind ja nicht bei VHDL. :-)

von Rolf M. (rmagnus)


Lesenswert?

Grrr! schrieb:
> Soll man sich also am besten selbst per
> const uint32_t true = 1U
> und
> const uint32_t false = 0U

In C würde das keine echten Konstanten erzeugen, in C++ wäre es es ein 
Fehler, daa true und false Schlüsselwörter sind.

> oder
> #define TRUE 0x00000001U
> und
> #define FALSE 0x00000000U
> selber was basteln?

Weder noch. Man sollte in C einfach #include <stdbool.h> machen (in C++ 
steht bool schon direkt zur Verfügung) und damit dann einfach das 
nehmen, was der Compilerbauer für am sinnvollsten erachtet hat.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> in C++ steht bool schon direkt zur Verfügung

In C steht es übrigens als _Bool auch direkt zur Verfügung. <stdbool.h> 
bildet das nur auf den namen bool ab. Dieser Name lag aber bei Code, der 
nach älteren Standards geschrieben worden ist, im "application 
namespace", weshalb man durch das unbedingte (ohne Notwendigkeit eines 
<stdbool.h>) Einführen von "bool" die Compilierbarkeit älteren Codes 
gebrochen hätte.

von Rolf M. (rmagnus)


Lesenswert?

Ja, und das gilt sinngemäß auch für _True und _False, die über das 
include auf true und false abgebildet werden.

von Bauform B. (bauformb)


Lesenswert?

Grrr! schrieb:
> Wie sieht es jetzt mit bool bei arm-none-eabi- aus?

Der "Procedure Call Standard for the Arm Architecture" (IHI 0042G aka 
ARM GENC 003534) sagt:
_Bool bzw. bool: unsigned byte; False = 0, True = 1
Die Compiler haben soweit eigentlich keine Wahl. Nur die Schreibweise 
für true und false ist anscheinend frei wählbar :)


Andere Architekturen brauchen ein wenig mehr Platz...
https://gcc.gnu.org/legacy-ml/gcc/1998-07/msg00139.html

: Bearbeitet durch User
von minifloat (Gast)


Lesenswert?

Grrr! schrieb:
> Wie sieht es jetzt mit bool bei arm-none-eabi- aus?[...]
> selber was basteln?

Wie sieht es auf der von dir verwendeten ARM-CPU bzw. Microcontroller 
mit bit-banding aus? Da wird nix mehr mit bool gemacht...

https://www.mikrocontroller.net/articles/ARM_Bitbanding schrieb:
> ARM Controller mit den Cores Cortex-M3 und -M4 sowie auch manche
> Cortex M0+ besitzen jedoch die Fähigkeit, einzelne Bits im RAM
> und im Peripheriebereich direkt adressieren zu können. Dazu
> existiert für den Peripheriebereich 0x40000000-0x400FFFFF ein
> weiterer Adressbereich 0x42000000-0x43FFFFFF und für den RAM-
> Bereich 0x20000000-0x200FFFFF der Bereich 0x22000000-0x23FFFFFF.
> Das sogenannte Bitbanding.

Gibt es inzwischen Compiler, die das Bit-banding auf native 
bool-ähnliche Datentypen abbilden?

mfg mf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

minifloat schrieb:
> bit-banding

Hat mit bool wenig zu tun. Einzelne Bits statt ganzer Bytes für Flags zu 
benutzen, hat auf einem 1-KiB-Controller wie ATtiny13 sicher Sinn, auf 
einem ARM mit mehreren 100 KiB SRAM spielt das kaum eine Rolle. Für 
ungenutzte Bytes zahlen einem die Hersteller ja keine Prämien. ;-)

Scheint sich aber ohnehin nicht so richtig durchgesetzt zu haben: 
Cortex-M7 unterstützt das gleich gar nicht mehr.

von Bauform B. (bauformb)


Lesenswert?

Jörg W. schrieb:
> Scheint sich aber ohnehin nicht so richtig durchgesetzt zu haben:
> Cortex-M7 unterstützt das gleich gar nicht mehr.

Es sieht so aus. Die M4-CPU in den STM32L4 unterstützt bit-banding wohl 
noch, aber es wird in den Datenblättern mit keiner Silbe erwähnt und die 
Peripherie ist so über den Adressraum verstreut, dass z.B. ADC, USB und 
GPIO(!) nicht per bit-banding erreichbar sind.

von Grrr! (Gast)


Lesenswert?

Danke für die Antworten! Die und ein bischen Abstand bzw. neuer Anlauf 
haben mein Verständnis dann doch weiter gebracht.
Ich habe jetzt einfach mal die Varianten uint32_t und bool in der IDE 
MCUXpresso in C++ ausgeführt und dann den disassembler bemüht. Wie Jörg 
schon schrieb: Der Compiler hält den bool dann in einem Register (also 
32 bit). Ob das bei einem größeren Programm auch noch so ist, weiß ich 
noch nicht. Aber ob Registerhaltung oder 8 bit-Zugriff mit Maskieren 
dann kriegsentscheident ist (also wenige Takte mehr), ist wohl zum Wohle 
der Lesbarkeit bei heutigen Controllern eher nebensächlich. Und wenn es 
wirklich eng sein sollte, weiß ich jetzt, wo ich "schrauben" könnte.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.