Was ist die Größe einer Ganzzahl in ATmega-Controllern in Bezug auf die Standarddatentypen? Und was bestimmt die Größe, ist es nur der Compiler? Oder liegt es am Hardware-Design des Controllers selbst und daher müssen sich alle ATmega-Compiler an diese Größe halten? Und wenn es an der Hardware liegt, wie kommt es, dass Sie in einem PC zwei verschiedene Compiler haben können, die unterschiedliche Ergebnisse für sizeof(int) liefern, obwohl sie auf demselben Prozessor laufen?
int
ist ein C-Typ. Die ATMega haben kein Konzept davon, sie arbeiten nur mit 8-Bit-Bytes (weil sie 8-Bit-AVR-CPUs haben).
Der Compiler konvertiert alle Operationen an int
Typen in die entsprechenden Operationen, die erforderlich sind, um diese Operation auf der von der CPU-Architektur geforderten Größenebene auszuführen. Für einen AVR wird er konvertiert, um Operationen auf Byteebene auszuführen, für eine 16-Bit-CPU würde dies erfolgen die 16bit Ebene usw.
avr-gcc
Ein Typ wird im int
Compiler einfach als 2-Byte-Integer definiert . Die Tatsache, dass es sich je nach Plattform ändert, bedeutet, dass Sie besser dran sind, die <stdint.h>
Typen zu verwenden, z. B. uint16_t
wenn Sie sicher sein möchten, wie groß der Code ist, der portierbar sein muss. Es sind Typen für alle standardmäßigen Integer-Größen (8,16,32,64) sowohl mit Vorzeichen als auch ohne Vorzeichen definiert.
Es gibt andere Definitionen für sogenannte _fast
Typen, die garantiert mindestens die erforderliche Größe haben, aber basierend auf der Plattform den schnellsten Code produzieren, zum Beispiel neigen 32-Bit-Prozessoren dazu, Operationen mit 32-Bit-Zahlen effizienter auszuführen als beispielsweise 8-Bit-Zahlen, also uint_fast8_t auf einer 32-Bit-Plattform wäre eine 32-Bit-Ganzzahl (es sind mindestens 8 Bit, aber schneller zu handhaben).
Die sizeof()
Anweisung wird zur Kompilierzeit ausgeführt und in eine Konstante umgewandelt, sie wird nicht vom Prozessor ausgeführt. avr-gcc
weiß, wie groß es ein int
als definiert hat, also weiß es, durch welche Konstante der sizeof()
Aufruf ersetzt werden muss.
uint_fast8_t
Sie könnten und zu Ihrer Liste
hinzufügen uint_least8_t
- wenn Sie diese zusammen mit verwenden uint8_t
(wenn eine feste Breite erforderlich ist), können Sie viel tragbareren Code schreiben.#include <stdint.h>
- ich hatte das erwähnt, aber der Textparser hatte es wegen des <> um ihn herum entfernt, sorry dafür, jetzt behoben.Die Größe von int
, short int
, long int
, usw. wird von den Leuten festgelegt, die den Compiler schreiben. Die Regeln von C lauten short int
<= int
<= long int
, aber das lässt viel Raum für die Compiler-Autoren.
Compiler-Autoren analysieren die Fähigkeiten der Prozessoren und versuchen, sinnvolle Entscheidungen für diese CPU zu treffen. Sie geben häufig Befehlszeilen-Flags an int
, um eine bestimmte Größe von an zu erzwingen, um das Portieren von Code zwischen Prozessoren zu erleichtern.
Der Compiler generiert verschiedene Codesequenzen, um unterschiedliche Int-Größen zu verarbeiten. Die CPU wird vom Code gesteuert und implementiert so die Größe, die durch die Ausgabe des Compilers definiert ist.
Die Atmegas verwenden die CPU-Architektur von AVR. Es verarbeitet meistens 8 Bit Daten gleichzeitig. Der Compiler muss also Code generieren, um Multibyte-Arithmetik zu implementieren.
Die zugrunde liegenden Adressräume der meisten ATmege sind 16 Bit, daher ist es sehr praktisch, eine Arithmetik zu haben, die auf all das zugreifen kann. Daher ist an standardmäßig int
16 Bit. In den „alten Tagen“ von x86 mit segmentiertem Speicher, wo Adressen 16 Bit oder 32 Bit betragen konnten und der Compiler angewiesen wurde, cde für ein bestimmtes „Modell“ zu generieren, generierte der Compiler normalerweise Code für eine Größe von int
, die die Größe halten konnte des Zeigers für dieses 'Speichermodell'.
Wenn Sie einen Compiler für denselben Prozessor verwenden, der in der Lage ist, Code für zwei (oder mehr) verschiedene Größen von int ( int
, nicht short int
, long int
, nur int
) zu generieren, dann ist dies genau das, was er als Reaktion auf die entsprechenden Flags (oder Pragmas) tut ).
Der Compiler „weiß“, für welche Größe int
er Code generiert, daher sizeof(int)
wird a vom Compiler zur Kompilierzeit durch den korrekten Wert ersetzt.
Die Größen der Standard-C-Datentypen werden durch die Compiler-Implementierung bestimmt. Laut Standard muss ein int Werte im Bereich von -32767 bis 32767 (16 Bit) enthalten können, darf aber größer sein. Die Größe eines Int ist normalerweise der natürlichste Wert für die CPU – die Wortgröße oder die Größe eines CPU-Registers.
Die einzige Möglichkeit, dies sicher zu wissen, besteht darin, Ihr Compiler-Handbuch zu konsultieren oder Testcode zu schreiben. Es ist eine gute Idee, eine Kopie des Handbuchs für einen Embedded-Compiler zu haben, da die Besonderheiten der Ausrichtung und Datenspeicherung bei der Embedded-Programmierung eher von Bedeutung sind. Wichtiger sind auch Compiler-Erweiterungen (zB für Interrupt-Unterstützung).
Wenn Sie einen C99-kompatiblen Compiler haben, ist es einfacher, die in definierten uintX_t-Typen zu verwenden, um die gewünschte Größe zu erhalten.
Als Referenz sind hier die Mindestgrößen für andere Datentypen aus Abschnitt 5.2.4.2.1 des C99-Standards aufgeführt. Beachten Sie, dass Zweierkomplement-Arithmetik nicht erforderlich ist, obwohl ich auf Anhieb keine Komplement- oder Vorzeichen-Größen-Maschinen kenne.
char (Bytegröße): sizeof(char) ist immer gleich 1. Zeichen mit Vorzeichen müssen Werte im Bereich von -127 bis 127 enthalten. Zeichen ohne Vorzeichen müssen Werte im Bereich von 0 bis 255 enthalten. Der Standard gibt auch die Mindestanzahl von Bits in a an Zeichen/Byte, also 8.
kurz: -32767 bis 32767 für signiert, 0 bis 65535 für unsigned. Entspricht 16 Bit.
int: Dasselbe wie kurz.
lang: -2147483647 bis 2147483647 für signiert, 0 bis 4294967295 für unsigned. Entspricht 32 Bit.
lang lang: -9223372036854775807 bis 9223372036854775807 für signiert, 0 bis 18446744073709551615 für unsigned. Entspricht 64 Bit.
Zeiger: Implementierung definiert. Der Standard erlaubt unterschiedliche "Darstellungs- und Ausrichtungsanforderungen" für Zeiger auf verschiedene Datentypen, aber das habe ich in der Praxis noch nie gesehen.
Tom Tischler
Spehro Pefhany
JimmyB
-mint8
. Die tatsächliche Größe hängt also davon ab, aber der Compiler weiß/entscheidet sich definitiv zur Kompilierzeit darüber.Alexander