Wie groß ist eine 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 sich um die Hardware handelt, wie kommt es dann, dass auf einem PC zwei verschiedene Compiler unterschiedliche Ergebnisse für sizeof (int) liefern können, selbst wenn sie auf demselben Prozessor ausgeführt werden?
microcontroller
c
atmega
embedded
Aelgawad
quelle
quelle
-mint8
. Die tatsächliche Größe hängt also davon ab, aber der Compiler weiß / entscheidet sich definitiv zur Kompilierungszeit dafür.Antworten:
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 auf
int
Typen in die entsprechenden Operationen, die erforderlich sind, um diese Operation auf der von der CPU-Architektur geforderten Größenebene auszuführen. Bei einem AVR wird er konvertiert, um Operationen auf Byte-Ebene auszuführen. Bei einer 16-Bit-CPU wird dies ausgeführt das 16bit Level usw.In
avr-gcc
einemint
Typ wird im Compiler einfach eine 2-Byte-Ganzzahl definiert . Die Tatsache, dass es sich je nach Plattform ändert, bedeutet, dass Sie das besser nutzen können<stdint.h>
Typen , z. B.uint16_t
wenn Sie sicher sein möchten, welche Codegröße tragbar sein muss. Für alle Standard-Ganzzahlgrößen (8,16,32,64) sind sowohl vorzeichenbehaftete als auch vorzeichenlose Typen definiert.Es gibt andere Definitionen für so genannte
_fast
Typen, die garantiert mindestens die erforderliche Größe haben, aber den schnellsten Code basierend auf der Plattform erzeugen. Beispielsweise führen 32-Bit-Prozessoren Operationen mit 32-Bit-Zahlen effizienter aus als beispielsweise 8-Bit-Zahlen, also uint_fast8_t Auf einer 32-Bit-Plattform wäre dies eine 32-Bit-Ganzzahl (mindestens 8 Bit, aber schneller zu handhaben).Der
sizeof()
Befehl wird zur Kompilierungszeit ausgeführt und in eine Konstante konvertiert. Er wird vom Prozessor nicht ausgeführt.avr-gcc
weiß, wie groß es als definiert hatint
, also weiß es, durch welche Konstante dersizeof()
Anruf ersetzt werden soll.quelle
uint_fast8_t
unduint_least8_t
zu Ihrer Liste hinzufügen -uint8_t
wenn Sie diese zusammen mit (wenn eine feste Breite erforderlich ist) verwenden, können Sie viel mehr portablen Code schreiben.#include <stdint.h>
- ich hatte das erwähnt, aber der Textparser hatte es wegen der <> um es herum entfernt, sorry, jetzt behoben.Die Größen
int
,short int
,long int
usw. werden von den Menschen entschieden , wer die Compiler schreiben. Die Regeln von C sindshort int
<=int
<=long int
, aber das lässt viel Platz 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 Befehlszeilenflags, um zu erzwingen
int
, dass eine bestimmte Größe angegeben wird, um das Portieren von Code zwischen Prozessoren zu vereinfachen.Der Compiler generiert verschiedene Codesequenzen, um unterschiedliche Größen von int zu verarbeiten. Die CPU wird vom Code gesteuert und implementiert so die durch die Compilerausgabe definierte Größe.
Die Atmega verwenden die CPU-Architektur von AVR. Meist werden 8 Bit Daten gleichzeitig verarbeitet. Der Compiler muss also Code generieren, um eine Multi-Byte-Arithmetik zu implementieren.
Die zugrunde liegenden Adressräume der meisten ATmeges 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, in denen Adressen 16 Bit oder 32 Bit sein konnten und der Compiler angewiesen war, cde für ein bestimmtes "Modell" zu generieren, generierte der Compiler normalerweise Code für eine Größe vonint
, die die Größe enthalten konnte des Zeigers für dieses 'Speichermodell'.Wenn Sie einen Compiler für den gleichen Prozessor verwenden, in der Lage Code für zwei (oder mehr) verschiedene Größen von int zu erzeugen (
int
nichtshort int
,long int
nurint
), dann ist das genau das , was sie als Reaktion auf den entsprechenden Flags tun werden (oder Pragma der ).Der Compiler 'weiß', für welche Größe
int
er Code generiert, sodass asizeof(int)
beim Compilieren vom Compiler durch den richtigen Wert ersetzt wird.quelle
Die Größen der Standard-C-Datentypen werden von der Compiler-Implementierung bestimmt. Gemäß dem Standard muss ein int Werte im Bereich von -32767 bis 32767 (16 Bit) enthalten können, kann jedoch 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, das Compiler-Handbuch zu konsultieren oder Testcode zu schreiben. Es ist eine gute Idee, eine Kopie des Handbuchs für einen eingebetteten Compiler zu haben, da die Besonderheiten der Ausrichtung und Datenspeicherung bei der eingebetteten Programmierung eher eine Rolle spielen. Wichtiger sind auch Compiler-Erweiterungen (z. B. zur 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 aufgeführt, die Abschnitt 5.2.4.2.1 des C99-Standards entnommen sind. Beachten Sie, dass die Zweierkomplementarithmetik nicht erforderlich ist, obwohl ich keine Komplement- oder Vorzeichengrößenmaschinen auf der Oberseite meines Kopfes kenne.
char (Bytegröße): sizeof (char) ist immer gleich 1. Vorzeichenbehaftete Zeichen müssen Werte im Bereich von -127 bis 127 enthalten. Vorzeichenlose Zeichen müssen Werte im Bereich von 0 bis 255 enthalten. Der Standard gibt auch die Mindestanzahl von Bits in a an char / byte, das ist 8.
kurz: -32767 bis 32767 für signiert, 0 bis 65535 für nicht signiert. Entspricht 16 Bit.
int: Wie kurz.
lang: -2147483647 bis 2147483647 für signiert, 0 bis 4294967295 für nicht signiert. Entspricht 32 Bit.
lang lang: -9223372036854775807 bis 9223372036854775807 für signiert, 0 bis 18446744073709551615 für nicht signiert. Entspricht 64 Bit.
Zeiger: Implementierung definiert. Der Standard erlaubt unterschiedliche "Darstellungs- und Ausrichtungsanforderungen" für Zeiger auf unterschiedliche Datentypen, aber das habe ich in der Praxis noch nie gesehen.
quelle