Kann ich davon ausgehen, dass die Größe von long int immer 4 Bytes beträgt?

73

Stimmt es immer, dass long int(was meines Wissens ein Synonym für ist long) 4Bytes sind?

Kann ich mich darauf verlassen? Wenn nicht, könnte dies für ein POSIX-basiertes Betriebssystem zutreffen?

Beseitigung
quelle
12
Nur um euch daran zu erinnern, dass sizeofPolsterung und Ausrichtung berücksichtigt werden. Es ist standardkonform, sizeof(unsigned long)8 Bytes zu haben, aber der Überlauf verhält sich wie 4 Bytes. Es ist völlig falsch zu versuchen, das Limit eines Integer-Typs zu verwenden sizeofund CHAR_BITSzu berechnen. Verwenden Sie, limits.hwenn es verwendet werden sollte.
user3528438
11
Sie sollten unbedingt die (zuerst gekürzte, dann die Vollversion der) C-FAQ lesen, die im Usenet zu einer Zeit entstanden ist, als sich dort Menschen mit Kenntnissen zu einem Thema am selben Ort versammelten (jetzt ist sie weit verbreitet) mehrere Seiten ...), und daher führte es zu unglaublich gründlichen und gut gemachten FAQs. Siehe c-faq.com/versions.html . Das Lesen ist ein Augenöffner für diese Frage und für Dutzende weitere, von denen Sie wahrscheinlich noch nicht einmal wissen, dass Sie sie wissen müssen (Abschnitt 5 - Nullzeiger - enthält häufig gestellte Fragen (FAQs), die ich schockiert (und dankbar) entdeckt habe)
Olivier Dulac
7
Nein, es ist 8 auf meinem PC
RiaD
3
Mögliches Duplikat des Wertebereichs in C Int und Long 32 - 64 Bit
TED
3
Auf den meisten 64-Bit-Systemen (z. B. x86-64 Linux und OS X) ist es 8. Windows ist die Hauptausnahme, da so viel Code für 32-Bit-Windows für 32-Bit-Windows geschrieben wurde, ohne dass Anstrengungen unternommen wurden, um tragbaren Code zu schreiben, der keine Annahme machte. Auch aus ABI-Gründen: Ich denke, einige Strukturen haben longs in ihren Definitionen, aber sie müssen nicht 64-Bit sein. Daher entschied sich MS für long32-Bit, um Strukturen in ihren ABIs und für vorhandene Codebasen gleich groß zu halten.
Peter Cordes

Antworten:

112

Die Standards sagen nichts über die genaue Größe von Ganzzahltypen aus char. In der Regel longist dies 32-Bit auf 32-Bit-Systemen und 64-Bit auf 64-Bit-Systemen.

Der Standard legt jedoch eine Mindestgröße fest . Aus Abschnitt 5.2.4.2.1 des C-Standards :

1 Die unten angegebenen Werte sind durch konstante Ausdrücke zu ersetzen, die für die Verwendung in #ifVorverarbeitungsrichtlinien geeignet sind . Darüber hinaus wird mit Ausnahme von CHAR_BITund MB_LEN_MAXdas Folgende durch Ausdrücke ersetzt, die denselben Typ haben wie ein Ausdruck, der ein Objekt des entsprechenden Typs ist, der gemäß den ganzzahligen Beförderungen konvertiert wurde. Ihre implementierungsdefinierten Werte müssen gleich oder größer (absoluter Wert) sein als die angegebenen Werte mit demselben Vorzeichen.

...

  • Mindestwert für ein Objekt vom Typ long int

    LONG_MIN -2147483647 // - (2 ^ 31−1)

  • Maximalwert für ein Objekt vom Typ long int

    LONG_MAX +2147483647 // 2 ^ 31−1

Dieses besagt , dass ein long int muss ein Minimum von 32 Bit sein, kann aber größer sein. Auf einem Computer mit CHAR_BIT8 ergibt dies eine minimale Bytegröße von 4. Auf einem Computer mit z. B. CHAR_BIT16 kann a long intjedoch 2 Byte lang sein.

Hier ist ein Beispiel aus der Praxis. Für den folgenden Code:

#include <stdio.h>

int main ()
{
    printf("sizeof(long) = %zu\n", sizeof(long));
    return 0;
}

Ausgabe unter Debian 7 i686:

sizeof (long) = 4

Ausgabe unter CentOS 7 x64:

sizeof (long) = 8

Nein, Sie können keine Annahmen zur Größe treffen. Wenn Sie einen Typ einer bestimmten Größe benötigen, können Sie die in definierten Typen verwenden stdint.h. Es definiert die folgenden Typen:

  • int8_t: 8-Bit signiert
  • uint8_t: vorzeichenloses 8-Bit
  • int16_t: 16-Bit signiert
  • uint16_t: vorzeichenloses 16-Bit
  • int32_t: signiertes 32-Bit
  • uint32_t: 32-Bit ohne Vorzeichen
  • int64_t: 64-Bit signiert
  • uint64_t: 64-Bit ohne Vorzeichen

Der stdint.hHeader ist in Abschnitt 7.20 der Norm beschrieben, die genauen Breitentypen in Abschnitt 7.20.1.1. Der Standard besagt, dass diese Typedefs optional sind, aber in den meisten Implementierungen vorhanden sind.

dbush
quelle
4
Aber diese Typedefs sind im Standard! Es ist nur die Implementierung definiert, ob sie tatsächlich existieren und welche Typen sie darstellen!
Vincent
10
@nouney verwechseln nicht die minimale Anzahl von Bits und die minimale Anzahl von Bytes. Ich erinnere mich an nichts, was es verbietet 1 == sizeof(char) == sizeof(int). Könnten Sie ein spezifisches Zitat aus dem Standard angeben, das besagt, dass " intmindestens 2 Bytes sind" ?
JFS
4
@nouney charkann größer als 8 Bit sein. Wenn es beispielsweise 32 Bit sind ( sizeofnatürlich immer noch 1), ist die Arbeit mit Daten wie 8-Bit-Textcodierungen schmerzhaft, aber im Allgemeinen werden solche Plattformen nicht für die Textverarbeitung verwendet.
Hyde
6
Ich würde nicht sagen, dass dies longnormalerweise 64-Bit ist, da es nicht unter Windows läuft und Windows weit verbreitet ist. Der Standard selbst definiert dies natürlich nicht, daher sind beide Implementierungen standardkonform, aber das Endergebnis sind Tonnen von Unix-C- (und C ++) Code, der 64-Bit-Zeiger unter Windows abschneidet (hören Sie einfach auf, Zeiger bereits in ganzen Zahlen zu speichern Verdammt !: D). Natürlich wird dies im Wesentlichen durch die Verwendung eines Typs verursacht, der standardmäßig einen Bereich von [−2147483647, +2147483647] hat, um Werte zu speichern, die größer als diese sind, was irgendwie lächerlich ist, aber
na ja
3
Ich habe immer gelernt, dass sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) und die Implementierung definiert ist.
Chris K
38

Nein, weder der C-Standard noch POSIX garantieren dies, und tatsächlich verfügen die meisten Unix-ähnlichen 64-Bit-Plattformen über 64 Bit (8 Byte) long.


quelle
Ints auf den meisten 32-Bit- und Up-Plattformen sind 32-Bit (AFAIK jedenfalls). Was wäre der Sinn eines Longs, der die gleiche Größe wie ein Int hat? Auf meinem System (Intel, 64-Bit-Linux, gcc) ist es 32 für int, 64 für lange.
Jamesqf
7
@jamesqf: Auf der überwiegenden Mehrheit der zwischen 1980 und 2005 veröffentlichten Plattformen betrug short 16 Bit, long 32 Bit und "int" 16 oder 32 Bit, um die Implementierung zu vereinfachen. Es war hilfreich, Typen mit fester Größe für 16- und 32-Bit-Typen zu haben, bevor C99 stdint.h hinzufügte. Als netter zusätzlicher Komplikationsfaktor für Letzteres kann int32_t auf einem System mit 32-Bit "int" mit "int" oder "long" kompatibel sein, aber konforme Implementierungen dürfen es nicht mit beiden kompatibel machen.
Supercat
19

Verwenden Sie Code sizeof(long int)und überprüfen Sie die Größe. Auf dem System, auf dem Sie gerade arbeiten, erhalten Sie die Größe von long int in Byte. Die Antwort auf Ihre Frage lautet insbesondere NEIN. Es ist nirgends in C oder in POSIX oder irgendwo garantiert.

Kevin Pandya
quelle
2
IMO, das beantwortet die Frage nicht.
Nouney
6
Es hat mir tatsächlich geholfen :)
Elimination
@nouney Wie beantwortet die Angabe, dass es keine exakte Größe gibt, die von den C-Standards garantiert wird, oder dass POSIX-Standards die Frage nicht beantworten? Es ist nicht die beste Antwort, aber sicherlich nicht falsch.
Leliel
3
@Leliel, weil die Antwort nur "use sizeof" war, als ich den Kommentar gepostet habe.
Nouney
sizeof(long int)Faktoren Polsterung und Ausrichtung Einschränkungen in das Ergebnis. Es ist vollkommen gültig sizeof, "16" zurückzugeben, selbst wenn Sie nur vier dieser Bytes verwenden dürfen.
Mark
13

Wie von @delnan hervorgehoben, behalten POSIX-Implementierungen die Größe von longund intwie nicht angegeben bei und unterscheiden sich häufig zwischen 32-Bit- und 64-Bit-Systemen.

Die Länge von longhängt hauptsächlich von der Hardware ab (häufig passend zur Größe der Datenregister auf der CPU und manchmal auch zu anderen softwarebezogenen Problemen wie dem Betriebssystemdesign und der ABI-Schnittstelle).

Es sizeofist keine Funktion, sondern eine Compiler-Direktive *, sodass Ihr Code bei der Verwendung keine Operationen verwendet sizeof- es ist dasselbe wie das Schreiben einer Zahl, nur dass er portabel ist.

verwenden:

sizeof(long int)

* Wie Dave in den Kommentaren hervorhob, sizeofwird zur Laufzeit berechnet, wenn es unmöglich ist, den Wert während der Kompilierung zu berechnen, z. B. wenn Arrays mit variabler Länge verwendet werden.

sizeofBerücksichtigt auch, wie in einem anderen Kommentar ausgeführt, die von der Implementierung verwendete Auffüllung und Ausrichtung, was bedeutet, dass die tatsächlich verwendeten Bytes von der Größe im Speicher abweichen können (dies kann beim Verschieben von Bits wichtig sein).

Wenn Sie nach Variablen stdint.hmit bestimmter Bytegröße suchen, sollten Sie ein Bytearray oder (ich würde davon ausgehen, dass dies unterstützt wird) die von C99 in definierten Typen verwenden - wie von @dbush vorgeschlagen.

Myst
quelle
4
Nicht (nur) Hardware. Sie können ein 32-Bit-Linux auf 64-Bit-Hardware ausführen, und Sie können sogar das x32-ABI verwenden, bei dem Datentypen die Größe von 32-Bit-Hardware haben, die Hardware jedoch tatsächlich im 64-Bit-Modus ausgeführt wird.
@ Delnan, yap, das stimmt. Ich sollte das wahrscheinlich klären , indem usuallyauf mostlyund eine Info in Klammern hinzuzufügen.
Myst
@delnan, ich wollte nicht über Ihre Antwort hinweggehen, ich dachte nur, es wäre am besten zu klären, dass sizeofes sich um eine Compiler-Direktive handelt, um alle wahrgenommenen Gründe zu beseitigen, die jemand für das Erraten der Größe haben könnte.
Myst
1
Kleine Korrektur: sizeofWird zur Laufzeit berechnet, wenn (und wenn) Sie ein Array mit variabler Länge oder einen variabel modifizierten Typ in C99 oder höher verwenden (oder 'gnu89' als GCC-Erweiterung), aber der meiste Code tut dies nicht.
Dave_thompson_085
13

Als wir C zum ersten Mal auf Hardware der ICL-Serie 39 implementiert haben, haben wir den Standard beim Wort genommen und die Datentypen der natürlichen Darstellung auf dieser Maschinenarchitektur zugeordnet, die short= 32 Bit, int= 64 Bit, long= 128 Bit war.

Wir haben jedoch festgestellt, dass keine ernsthaften C-Anwendungen funktionieren. Sie alle nahmen das Mapping short= 16, int= 32, long= 64 an, und wir mussten den Compiler ändern, um dies zu unterstützen.

Was auch immer der offizielle Standard sagt, seit vielen Jahren konvergiert jeder auf long= 64 Bit und es ist unwahrscheinlich, dass sich dies ändert.

Michael Kay
quelle
2
"Ja wirklich?" Zumindest unter GCC / Glibc / GNU / Linux scheinen Plattformen auf int = 32, long long = 64, long = native Wortgröße (entweder 32 oder 64) und sicherlich nicht long = 64 zu konvergieren. ZB auf x86 Nicht gerade eine Nischenarchitektur, lang ist 32 Bit. OSX, Solaris, z / OS, SysV sind einige andere Betriebssysteme, die dieser Konvention folgen.
Jörg W Mittag
Für ein noch weiter verbreitetes System als OSX, Linux, z / OS oder SysV gibt es Windows, das eine andere Konvention hat als Sie (immer 64) oder solche (immer das gleiche wie ein Zeiger), nämlich immer 32 Bit .
Jörg W Mittag
IMHO wäre das richtige Mittel, ein Standardmittel zu haben, mit dem Code angeben kann, welche Art von "int", "long" usw. in bestimmten Kontexten erforderlich sind [normalerweise pro Datei, so dass eine Header-Datei, die eine Funktion als deklariert "int" zu akzeptieren hat immer die gleiche Bedeutung]. Ein 64-Bit-System zu haben, das ein 16-Bit- oder 32-Bit- "int" emuliert, sollte ziemlich einfach sein und wäre wahrscheinlich zuverlässiger als der Versuch, den Code angesichts all der merkwürdigen kleinen Nuancen in C anzupassen (wie die Tatsache, dass auf einem 64 -bit-System, uint32_t modulare Multiplikation funktioniert nicht für alle Werte).
Supercat
11

Der Standard sagt nichts über die Größe von aus long int, daher hängt er von der Umgebung ab, die Sie verwenden.

Um die Größe long intIhrer Umgebung zu ermitteln, können Sie den sizeofOperator verwenden und die Größe von ermitteln long int. Etwas wie

sizeof(long int)

Der C-Standard erfordert nur die folgenden Punkte zu den Größen der Typen

  • int> = 16 Bit,
  • lang> = 32 Bit,
  • lang lang (seit C99)> = 64 Bit
  • sizeof (char) <= sizeof (kurz) <= sizeof (int) <= sizeof (lang) <= sizeof (lang lang)
  • sizeof (char) == 1
  • CHAR_BIT> = 8

Die übrigen sind definierte Implementierungen, daher ist es nicht verwunderlich, wenn man auf Systeme stößt, in denen int 18/24/36/60 Bits hat, die komplement-signierte Form, sizeof (char) == sizeof (short) == sizeof (int) == sizeof (long) == 4, 48-Bit lang oder 9-Bit-Zeichen wie exotische Architekturen, die den Standardausschüssen am Herzen liegen, und Liste der Plattformen, die vom C-Standard unterstützt werden

Der obige Punkt über long int ist völlig falsch. Die meisten Linux / Unix-Implementierungen definieren Long als 64-Bit-Typ, aber es sind nur 32 Bit in Windows, da sie unterschiedliche Datenmodelle verwenden (siehe Tabelle hier 64-Bit-Computing ), und dies ist unabhängig von 32 oder 64-Bit OS Version.

Quelle

Rahul Tripathi
quelle
7

Der Compiler bestimmt die Größe basierend auf dem Hardwaretyp und dem Betriebssystem.

Daher sollten keine Annahmen bezüglich der Größe getroffen werden.

Karthik Balaguru
quelle
1

Nein, das können Sie nicht annehmen, da die Größe des "langen" Datentyps von Compiler zu Compiler unterschiedlich ist. Weitere Informationen finden
Sie in diesem Artikel.

Revnic Robert-Nick
quelle
0

Kurze Antwort: Nein! Sie können keine festen Annahmen über die Größe von treffen long int. Weil der Standard (C-Standard oder POSIX) die Größe von nicht dokumentiertlong int (wie wiederholt betont). Um nur ein Gegenbeispiel zu Ihrer Überzeugung zu liefern, haben die meisten 64-Bit-Systeme die longGröße 64! Um die Portabilität zu maximieren, verwenden Sie sie sizeofangemessen.

Verwenden Sie sizeof(long int)diese Option , um die Größe zu überprüfen. Sie gibt die Größe longin Byte zurück. Der Wert ist system- oder umgebungsabhängig. Das heißt, der Compiler bestimmt die Größe basierend auf der Hardware und dem Betriebssystem.

Ehsan
quelle
0

Aus Usrmiscs Blog:

Der Standard überlässt es vollständig dem Compiler, was auch bedeutet, dass derselbe Compiler es von Optionen und Zielarchitektur abhängig machen kann.

Also kannst du nicht .

Übrigens long intkönnte sogar das gleiche sein wie long.

simhumileco
quelle
Was ist los mit dieser Antwort? Warum hat ihr jemand einen negativen Punkt gegeben? Immerhin ist es die Antwort auf die Frage und zeichnet sich durch ihre Einfachheit im Vergleich zu anderen Antworten aus, was für einige Leute wichtig sein kann, die nach einer Antwort suchen. Ist es nicht?
simhumileco