Was bestimmt sizeof (int)

7

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?

Aelgawad
quelle
4
Der Compiler tut es.
Tom Carpenter
1
Der Compiler hat eine feste Breite für int. Ein standardkonformer Compiler muss eine Mindestbreite für int (16 Bit) verwenden, es gibt jedoch keine maximale Breite. Daher können zwei kompatible Compiler unterschiedliche Breiten verwenden, obwohl sie Code für dieselbe Plattform ausgeben.
Spehro Pefhany
@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 Kompilierungszeit dafür.
JimmyB
Wenn Ihre Frage beantwortet wurde, können Sie bitte eine der Antworten als akzeptiert markieren?
Alexander - Reinstate Monica

Antworten:

12

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 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-gcceinem intTyp 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_twenn 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-gccweiß, wie groß es als definiert hat int, also weiß es, durch welche Konstante der sizeof()Anruf ersetzt werden soll.

Tom Carpenter
quelle
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 bereitstellen?
Gbulmer
2
Sie können uint_fast8_tund uint_least8_tzu Ihrer Liste hinzufügen - uint8_twenn Sie diese zusammen mit (wenn eine feste Breite erforderlich ist) verwenden, können Sie viel mehr portablen Code schreiben.
David
avr-gcc scheint den Typ int8_t nicht zu erkennen. Vermisse ich etwas
Aelgawad
1
@BlackyDucky müssen Sie #include <stdint.h>- ich hatte das erwähnt, aber der Textparser hatte es wegen der <> um es herum entfernt, sorry, jetzt behoben.
Tom Carpenter
6

Die Größen int, short int, long intusw. werden von den Menschen entschieden , wer die Compiler schreiben. Die Regeln von C sind short 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 int16 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 ( intnicht short int, long intnur int), 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 inter Code generiert, sodass a sizeof(int)beim Compilieren vom Compiler durch den richtigen Wert ersetzt wird.

gbulmer
quelle
5

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.

Adam Haun
quelle