Was bestimmt sizeof(int)

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?

Der Compiler tut es.
Der Compiler hat eine feste Breite für int. Ein standardkonformer Compiler muss eine Mindestbreite für int (16 Bit) verwenden, es gibt jedoch kein Maximum, sodass zwei konforme Compiler unterschiedliche Breiten verwenden könnten, obwohl sie Code für dieselbe Plattform ausgeben.
@SpehroPefhany Ich würde eher sagen: "Der Compiler kennt die Größe beim Kompilieren." - Es kann je nach Zielplattform variieren, und es gibt Dinge wie -mint8. Die tatsächliche Größe hängt also davon ab, aber der Compiler weiß/entscheidet sich definitiv zur Kompilierzeit darüber.
Wenn Ihre Frage beantwortet wurde, können Sie bitte eine der Antworten als akzeptiert markieren?

Antworten (3)

intist 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 intTypen 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-gccEin Typ wird im intCompiler 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_twenn 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 _fastTypen, 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-gccweiß, wie groß es ein intals definiert hat, also weiß es, durch welche Konstante der sizeof()Aufruf ersetzt werden muss.

Ich glaube nicht, dass int als irgendetwas typisiert ist. Ich denke, der Compiler "entscheidet", die Entscheidung ist in den Compiler eingebaut. Können Sie einen Link oder Beweise angeben?
uint_fast8_tSie 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.
avr-gcc scheint den int8_t-Typ nicht zu erkennen. Übersehe ich etwas?
@BlackyDucky du musst #include <stdint.h>- ich hatte das erwähnt, aber der Textparser hatte es wegen des <> um ihn herum entfernt, sorry dafür, jetzt behoben.
Wenn man weiß, dass die AVRs nativ 8-Bit sind, kann es die Frage aufwerfen, warum nicht einfach "int" 8-Bit für AVR-GCC machen - der Grund dafür ist, dass die C-Sprache erfordert, dass "int" mindestens 16 Bit / 2 Zeichen, also 8 Bit würde es nicht mit dem C-Standard konform machen (und einige Annahmen, wie z. B. dass int ein größerer Typ als char ist, werden auch nicht wahr sein). Mathematik mit 8-Bit-Typen (char / uint8_t) ist normalerweise immer noch schneller, da einzelne mathematische 16-Bit-Ausdrücke in mehrere 8-Bit-Anweisungen kompiliert werden müssen.

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 int16 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 inter 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.