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)
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 intmuss 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:
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.
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.
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.
@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(longint)
* 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.
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.
"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(longint)
Der C-Standard erfordert nur die folgenden Punkte zu den Größen der Typen
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.
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.
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.
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.
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?
sizeof
Polsterung 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 verwendensizeof
undCHAR_BITS
zu berechnen. Verwenden Sie,limits.h
wenn es verwendet werden sollte.long
s in ihren Definitionen, aber sie müssen nicht 64-Bit sein. Daher entschied sich MS fürlong
32-Bit, um Strukturen in ihren ABIs und für vorhandene Codebasen gleich groß zu halten.Antworten:
Die Standards sagen nichts über die genaue Größe von Ganzzahltypen aus
char
. In der Regellong
ist 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 :
Dieses besagt , dass ein
long int
muss ein Minimum von 32 Bit sein, kann aber größer sein. Auf einem Computer mitCHAR_BIT
8 ergibt dies eine minimale Bytegröße von 4. Auf einem Computer mit z. B.CHAR_BIT
16 kann along int
jedoch 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:
Ausgabe unter CentOS 7 x64:
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 signiertuint8_t
: vorzeichenloses 8-Bitint16_t
: 16-Bit signiertuint16_t
: vorzeichenloses 16-Bitint32_t
: signiertes 32-Bituint32_t
: 32-Bit ohne Vorzeichenint64_t
: 64-Bit signiertuint64_t
: 64-Bit ohne VorzeichenDer
stdint.h
Header 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.quelle
1 == sizeof(char) == sizeof(int)
. Könnten Sie ein spezifisches Zitat aus dem Standard angeben, das besagt, dass "int
mindestens 2 Bytes sind" ?char
kann größer als 8 Bit sein. Wenn es beispielsweise 32 Bit sind (sizeof
natü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.long
normalerweise 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, aberNein, 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
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.quelle
sizeof(long int)
Faktoren Polsterung und Ausrichtung Einschränkungen in das Ergebnis. Es ist vollkommen gültigsizeof
, "16" zurückzugeben, selbst wenn Sie nur vier dieser Bytes verwenden dürfen.Wie von @delnan hervorgehoben, behalten POSIX-Implementierungen die Größe von
long
undint
wie nicht angegeben bei und unterscheiden sich häufig zwischen 32-Bit- und 64-Bit-Systemen.Die Länge von
long
hä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
sizeof
ist keine Funktion, sondern eine Compiler-Direktive *, sodass Ihr Code bei der Verwendung keine Operationen verwendetsizeof
- es ist dasselbe wie das Schreiben einer Zahl, nur dass er portabel ist.verwenden:
sizeof(long int)
* Wie Dave in den Kommentaren hervorhob,
sizeof
wird 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.sizeof
Berü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.h
mit 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.quelle
usually
aufmostly
und eine Info in Klammern hinzuzufügen.sizeof
es 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.sizeof
Wird 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.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.quelle
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 int
Ihrer Umgebung zu ermitteln, können Sie densizeof
Operator verwenden und die Größe von ermittelnlong int
. Etwas wiesizeof(long int)
Quelle
quelle
Der Compiler bestimmt die Größe basierend auf dem Hardwaretyp und dem Betriebssystem.
Daher sollten keine Annahmen bezüglich der Größe getroffen werden.
quelle
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.
quelle
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 dielong
Größe 64! Um die Portabilität zu maximieren, verwenden Sie siesizeof
angemessen.Verwenden Sie
sizeof(long int)
diese Option , um die Größe zu überprüfen. Sie gibt die Größelong
in 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.quelle
Aus Usrmiscs Blog:
Also kannst du nicht .
Übrigens
long int
könnte sogar das gleiche sein wielong
.quelle