Warum ist sizeof für eine Struktur, die gleich der Summe der sizeof eines jeden Mitglieds?
Warum die sizeof
Betreiber zurück eine Größe größer, für eine Struktur, die als die Summe der Größen der Struktur der Mitglieder?
Siehe das C-FAQ auf Speicher alighnment. c-faq.com/struct/align.esr.html
Anekdote: Es war eine wirkliche computer-virus, der seinen code in struct-Polster in das host-Programm.
Das ist beeindruckend! Ich hätte nie gedacht es möglich, mit solchen kleinen Bereichen für alles. Sind Sie in der Lage zu leisten, mehr details?
Ich bin mir sicher, dass es beteiligt viel von jmp.
Siehe Struktur Polsterung, Verpackung: Die Verlorene Kunst des C-Struktur-Verpackung Eric S. Raymond
Anekdote: Es war eine wirkliche computer-virus, der seinen code in struct-Polster in das host-Programm.
Das ist beeindruckend! Ich hätte nie gedacht es möglich, mit solchen kleinen Bereichen für alles. Sind Sie in der Lage zu leisten, mehr details?
Ich bin mir sicher, dass es beteiligt viel von jmp.
Siehe Struktur Polsterung, Verpackung: Die Verlorene Kunst des C-Struktur-Verpackung Eric S. Raymond
InformationsquelleAutor Kevin | 2008-09-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist wegen der Polsterung Hinzugefügt befriedigen alignment-constraints. Daten, die Ausrichtung der Struktur Auswirkungen auf Leistung und Korrektheit von Programmen:
SIGBUS
).Hier ist ein Beispiel mit typischen Einstellungen für einen x86-Prozessor (alle verwendeten 32-und 64-bit-Modus):
Kann man minimieren der Größe der Strukturen durch die Sortierung der Mitglieder nach Ausrichtung (Sortierung nach Größe genügt auch für die, die in basic-Typen) (wie Struktur
Z
im Beispiel oben).WICHTIGER HINWEIS: Sowohl die C-und C++ - standards Staates, die Ausrichtung der Struktur ist durch die Implementierung festgelegt. Deshalb kann jeder compiler kann wählen, richten Sie die Daten unterschiedlich, was unterschiedliche und inkompatible Daten-layouts. Aus diesem Grund beim Umgang mit Bibliotheken verwendet werden, die von unterschiedlichen Compilern, es ist wichtig zu verstehen, wie der Compiler die richten Daten. Einige Compiler haben Befehlszeile-Einstellungen und/oder spezielle
#pragma
Anweisungen zum ändern der Struktur-alignment-Einstellungen.Die x86-chips sind eigentlich ziemlich eindeutig, denn Sie ermöglichen den nichtlinearen Zugriff, wenn auch bestraft; AFAIK die meisten chips Ausnahmen, nicht nur ein paar. PowerPC ist ein anderes häufiges Beispiel.
Aktivieren pragmas für die unaligned-Zugriffe in der Regel dazu, Ihren code zu Ballon in der Größe, die auf Prozessoren, die werfen Verlagerung Fehler, als code zu reparieren, jede Fehlausrichtung erzeugt werden. ARM wirft Verlagerung Fehler.
völlig einverstanden. Aber die meisten desktop-Prozessoren sind x86/x64, also die meisten chips keine Daten der alignment-Fehler 😉
Unaligned Zugriff auf Daten ist in der Regel eine Funktion, die in CISC-Architekturen, und die meisten RISC-Architekturen nicht (ARM, MIPS, PowerPC, Cell). In eigentlich die meisten chips sind KEINE desktop-Prozessoren, die für embedded-Regel durch die Anzahl der chips und die überwiegende Mehrheit von Ihnen sind RISC-Architekturen.
InformationsquelleAutor
Verpackung und byte-Ausrichtung, wie beschrieben in der C-FAQ hier:
das ist nicht möglich. Der compiler ist darf nicht anordnen struct Mitglieder obwohl der gcc hat eine experimentelle option, das zu tun,
InformationsquelleAutor EmmEff
Wenn Sie möchten, dass die Struktur zu einer bestimmten Größe mit GCC zum Beispiel verwenden
__attribute__((packed))
.Unter Windows können Sie die Ausrichtung auf ein byte bei der Verwendung der cl.exe compier mit der /Zp-option.
In der Regel ist es leichter für die CPU auf Daten zugreifen, die ein Vielfaches von 4 (oder 8), je nach Plattform und auch auf den compiler an.
So ist es eine Frage der Ausrichtung grundsätzlich.
Müssen Sie gute Gründe haben, um es zu ändern.
Alles ist ok, außer wenn Sie erwähnen das Betriebssystem. Dies ist ein Problem für die CPU-Geschwindigkeit, das Betriebssystem ist nicht auf allen beteiligten.
Ein weiterer guter Grund ist wenn Sie die Füllung ein-Datenstrom in ein struct, z.B. bei der Analyse Netzwerk-Protokolle.
Ich wies darauf hin, dass "es einfacher ist, für das Eins-System auf Daten zugreifen" ist falsch, da das OS nicht auf die Daten zugreifen.
In der Tat, man sollte reden über die ABI (application binary interface). Standard-Ausrichtung (wird verwendet, wenn Sie sich nicht ändern, es in der Quelle) ist abhängig von der ABI, und viele OSs-Unterstützung für mehrere ABIs (sagen wir, 32 - und 64-bit, oder für Programme von verschiedenen Betriebssystemen, oder unterschiedliche Möglichkeiten der Zusammenstellung der gleichen Binärdateien für das gleiche OS). OTOH, was alignment ist performancetechnisch praktisch hängt von der CPU - Speicher zugegriffen wird, die gleiche Weise, ob Sie 32-oder 64-bit-Modus (ich kann nicht kommentieren, real-Modus, scheint aber kaum relevant für die Leistung heute). IIRC Pentium begann die lieber 8-byte-Ausrichtung.
InformationsquelleAutor
Dies kann durch eine byte-Ausrichtung und Polsterung, so dass die Struktur kommt eine gerade Anzahl von bytes (oder Worten) auf Ihrer Plattform. Zum Beispiel in C auf Linux, die folgenden 3 Strukturen:
Haben Mitglieder, die die Größe (in bytes) 4 bytes (32 bits) 8 bytes (2x 32 bit) und 1 byte (2+6 bit) bzw. Das obige Programm (unter Linux mit gcc) druckt den Größen 4, 8, 4, wo die Letzte Struktur ist gepolstert, so dass es ein einzelnes Wort ist (4 x 8-bit-bytes, die auf meinem 32bit-Plattform).
-@Kyle Burton . Entschuldigen Sie mich, ich verstehe nicht, warum die Größe der Struktur "someBits" ist gleich 4, ich erwarte von 8 bytes, da gibt es 2 Integer deklariert (2*sizeof(int)) = 8 bytes. Dank
Hi @youpilat13, die
:2
und:6
sind eigentlich die Angabe 2 und 6 bits, nicht volle 32-bit-Ganzzahlen in diesem Fall. someBits.x, nur 2 bits können nur speichern Sie 4 mögliche Werte: 00, 01, 10 und 11 (1, 2, 3 und 4). Macht das Sinn? Hier ist ein Artikel über die Funktion: geeksforgeeks.org/bit-fields-cInformationsquelleAutor Kyle Burton
Siehe auch:
für Microsoft Visual C:
http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx
- und GCC-Forderung die Kompatibilität mit den Microsoft-compiler.:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
In Ergänzung zu den bisherigen Antworten, bitte beachten Sie, dass unabhängig von der Verpackung, es gibt keine Mitglieder -, um-Garantie in C++. Compiler können (und sicherlich nicht) der Sie virtuelle Tabelle Zeiger und die Basis-Strukturen " - Mitglieder auf die Struktur. Sogar die Existenz der virtuellen Tabelle ist nicht gewährleistet, die von der Norm (virtuellen Mechanismus die Umsetzung ist nicht angegeben) und daher kann man den Schluss ziehen, dass eine solche Garantie ist unmöglich.
Ich bin ziemlich sicher, dass Mitglied -, um ist garantiert in C, aber ich würde nicht damit rechnen, beim schreiben von cross-Plattform-oder cross-compiler-Programm.
es gibt eine gewisse Ordnung garantieren, in C++: "nicht-statische Daten-member of a (non-union) der Klasse deklariert, ohne zwischengeschalteten access-specifier reserviert werden, so dass später die Mitglieder haben eine höhere Adressen in einem class-Objekt"
InformationsquelleAutor lkanab
Die Größe einer Struktur ist mehr als die Summe seiner Teile, weil, was heißt Verpackung. Ein Prozessor hat eine bevorzugte Größe der Daten, dass es funktioniert. Die meisten modernen Prozessoren " bevorzugte Größe, wenn 32-bit (4 bytes). Zugriff auf den Speicher, wenn die Daten auf diese Art der Grenze ist effizienter als die Dinge, die Spagat, die Größe-Grenze.
Zum Beispiel. Betrachten Sie die einfache Struktur:
Wenn die Maschine eine 32-bit-Maschine und Daten ausgerichtet ist, auf einem 32-bit-Grenze, sehen wir ein unmittelbares problem (vorausgesetzt, dass kein Struktur-alignment). In diesem Beispiel lassen Sie uns annehmen, dass die Struktur der Daten beginnt bei der Adresse 1024 (0 x 400 - beachten Sie, dass die niedrigsten 2 bits null sind, also die Daten, die ausgerichtet ist, um eine 32-bit-Grenze). Der Zugriff auf die Daten.einer wird funktionieren, weil Sie beginnt, auf eine Grenze - 0 x 400. Der Zugriff auf die Daten.b wird auch funktionieren, weil es unter der Adresse 0x404 - andere 32-bit-Grenze. Aber einen nichtlinearen Struktur würde Daten.c an der Adresse 0x405. Die 4 bytes der Daten.c sind 0x405, 0x406, 0x407, 0x408. Auf einem 32-bit-Maschine, würde das system die Daten Lesen.c während ein Speicher-Zyklus, würde aber nur 3 der 4 Byte (das 4. byte ist die nächste Grenze). So würde das system um einen zweiten Zugang zum Speicher zu erhalten, das 4. byte,
Nun, wenn, anstatt Daten.c an der Adresse 0x405, der compiler gepolsterte die Struktur von 3 bytes und die Daten.c an der Adresse 0x408, dann würde das system nur noch 1 Zyklus, um Daten zu Lesen, schneiden Zugriffszeit auf die Daten-element um 50%. Polsterung swaps Speicher-Wirkungsgrad für die Effizienz der Verarbeitung. Da Computer können riesige Mengen an Speicher (viele Gigabyte), wird der Compiler das Gefühl, dass die swap - (speed over size) vernünftig.
Leider, dieses problem wird ein killer, wenn Sie versuchen zu senden-Strukturen über ein Netzwerk oder sogar das schreiben der binären Daten in einer binary-Datei. Die Polsterung eingefügt zwischen den Elementen einer Struktur oder Klasse zerstören kann, die Daten gesendet zu der Datei oder dem Netzwerk. Um write portable code (eine, die gehen, um verschiedene Compiler), werden Sie wahrscheinlich haben, um Zugriff auf jedes element der Struktur einzeln, um sicherzustellen, dass die richtige "Verpackung".
Auf der anderen Seite, verschiedene Compiler besitzen verschiedene Fähigkeiten, die zum verwalten von Daten Struktur-Verpackung. Zum Beispiel in Visual C/C++ - compiler unterstützt die #pragma pack Befehl. Dies ermöglicht es Ihnen, Daten anpassen Verpackung und Ausrichtung.
Beispiel:
Ich soll jetzt die Länge von 11. Ohne das pragma, ich könnte alles sein, von 11 bis 14 (und für einige Systeme, so viel wie 32), abhängig von der Standard-Verpackung der compiler.
"... denn was heißt Verpackung. ... -- ich denke du meinst "Polsterung". "die Meisten modernen Prozessoren " bevorzugte Größe, wenn 32-bit (4 bytes)" -- Das ist eine starke Vereinfachung. In der Regel Größen von 8, 16, 32 und 64 bit werden unterstützt; oft jede Größe hat Ihre eigene Ausrichtung. Und ich bin mir nicht sicher, deine Antwort fügt keine neuen Informationen, die nicht bereits in der akzeptierten Antwort.
WhenI sagte die Verpackung, ich meinte, wie der compiler packt die Daten in eine Struktur (und er kann dies tun, durch die Polsterung der kleinen Elemente, aber es muss nicht pad ist, aber es immer packs). Wie für die Größe - ich Sprach über die Architektur des Systems, nicht das, was das system Unterstützung für Zugriff auf Daten (die Art unterscheidet sich von der zugrunde liegenden bus-Architektur). Für Ihren letzten Kommentar, habe ich eine vereinfachte und erweiterte Erklärung für einen Aspekt der Abwägung (Geschwindigkeit vs. Größe) - eine große Programmier-problem. Ich beschreiben auch einen Weg, um das problem zu beheben - das war nicht in der akzeptierten Antwort.
"Verpackung" in diesem Kontext bezieht sich normalerweise auf die Zuteilung der Mitglieder stärker als die Standard, als mit
#pragma pack
. Wenn Mitglieder zugeteilt werden, auf Ihre default-Ausrichtung, würde ich im Allgemeinen sagen, die Struktur ist nicht gepackt.Die Verpackung ist schon ein überladener Begriff. Es bedeutet, wie Sie die Struktur-Elemente in den Speicher. Ähnlich wie die Bedeutung des Stellens von Gegenständen in eine Schachtel (Verpackung für den Umzug). Es auch bedeutet, dass Elemente in den Speicher, ohne Polsterung (Art kurzer hand für "dicht gepackt"). Dann gibt es den Befehl version des Wortes in der #pragma pack Befehl.
InformationsquelleAutor sid1138
Er kann dies tun, wenn Sie-implizit oder explizit-legen Sie die Ausrichtung der Struktur. Eine Struktur, die ausgerichtet ist 4, wird immer ein Vielfaches von 4 bytes, selbst wenn die Größe Ihrer Mitglieder, wäre es etwas, das nicht ein Vielfaches von 4 bytes.
Auch eine Bibliothek kompiliert werden, die unter x86 mit 32-bit-Ganzzahlen und Sie können vergleichen, werden seine Komponenten auf einem 64-bit-Prozess würde Ihnen ein anderes Ergebnis, wenn Sie Taten dies mit der hand.
InformationsquelleAutor Orion Adrian
C99 N1256 standard-Entwurf
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
6.5.3.4 Den sizeof-operator:
6.7.2.1 Struktur-und union-Bezeichner:
und:
Dem neuen C99 - flexible array-member-Funktion (
struct S {int is[];};
) kann auch beeinflussen Polsterung:Anhang J portabilitätsprobleme bekräftigt:
C++11 N3337 standard-Entwurf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
5.3.3 Sizeof:
9.2 die Schüler:
Ich kenne nur genug C++ zu verstehen, den Hinweis 🙂
InformationsquelleAutor Ciro Santilli 新疆改造中心996ICU六四事件
Zusätzlich zu den anderen Antworten, ein struct kann (meistens aber nicht) haben virtuelle Funktionen, in welchem Fall die Größe der Struktur wird auch der Speicherplatz für die vtbl.
InformationsquelleAutor JohnMcG
C-Sprache lässt compiler einige Freiheit über die Lage, die strukturellen Elemente in den Speicher:
Die C-Sprache bietet eine gewisse Sicherheit für den Programmierer, der die layout-Elemente in der Struktur:
Probleme im Zusammenhang mit den Elementen Ausrichtung:
, Wie die Ausrichtung funktioniert:
Ende, so dass das erste element des als Nächstes folgenden Struktur nicht gegen die Anforderungen der Ausrichtung
p.s genauere Infos gibt es hier: "Samuel P. Harbison, Guy L. Steele C-A Reference, (5.6.2 - 5.6.7)"
InformationsquelleAutor bruziuz
Die Idee ist, dass für die Geschwindigkeit und cache überlegungen, die Operanden gelesen werden sollte von Adressen ausgerichtet auf Ihre Natürliche Größe. Um dies möglich zu machen, der compiler füllt die Struktur der Mitglieder, so dass die folgenden Mitglied oder folgenden Struktur ausgerichtet werden.
Die x86-Architektur war schon immer in der Lage zu Holen, nicht ausgerichtete Adressen. Allerdings ist es langsamer und wenn der Versatz überschneidungen zwei verschiedene cache-Zeilen, dann ist es evicts zwei cache-lines, wenn ein ausgerichteter Zugriff würde nur vertreiben.
Einige Architekturen haben tatsächlich Falle auf falsch liest und schreibt, und frühe Versionen der ARM-Architektur (die, die sich in allen heutigen mobile CPUs) ... naja, Sie eigentlich nur zurückgegeben, falsche Daten auf. (Sie ignoriert die low-order bits.)
Schließlich ist zu beachten, dass die cache-Zeilen beliebig groß werden kann, und der compiler versucht nicht, zu erraten, an jenen oder einen Platz-vs-speed-Nachteil. Stattdessen wird die Ausrichtung der Entscheidungen sind Teil des ABI und repräsentieren die minimale Ausrichtung, die letztendlich gleichmäßig füllen eine cache-line.
TL;DR: Ausrichtung ist wichtig.
InformationsquelleAutor DigitalRoss