Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 17 Strukturen
  gp 17.1 Struktur deklarieren
  gp 17.2 Initialisierung und Zugriff auf Strukturen
  gp 17.3 Strukturen als Wertübergabe an eine Funktion
  gp 17.4 Strukturen als Rückgabewert einer Funktion
  gp 17.5 Strukturen vergleichen
  gp 17.6 Arrays von Strukturen
  gp 17.7 Strukturen in Strukturen (Nested Structures)
  gp 17.8 Kurze Zusammenfassung zu den Strukturen
  gp 17.9 Union
  gp 17.10 Aufzählungstyp enum
  gp 17.11 Typendefinition mit typedef
  gp 17.12 Attribute von Strukturen verändern (nicht ANSI C)
  gp 17.13 Bitfelder
  gp 17.14 Das offsetof-Makro


Galileo Computing - Zum Seitenanfang

17.12 Attribute von Strukturen verändern (nicht ANSI C)  toptop

Der Speicherplatz für eine Struktur wird – wie schon bei den Arrays – lückenlos im Hauptspeicher abgelegt. Damit das System schneller auf diese Daten im Hauptspeicher zurückgreifen kann, werden diese in zwei oder in durch vier teilbare Adressen angeordnet. Dies ist abhängig vom Betriebssystem. Dabei wird einiges an Speicherplatz verschwendet. Zur Demonstration dient das folgende Programm:

/* alignment1.c */
#include <stdio.h>
#include <stdlib.h>
struct speicher {
   char x;
   int z;
};
int main(void) {
   struct speicher test;
   printf("%ld Bytes\n",sizeof(test));
   return EXIT_SUCCESS;
}

Auf 32-Bit-Systemen dürfte diese Struktur acht Byte benötigen. Und dies, obwohl es eigentlich fünf Byte sein sollten (char + int = 5 Byte).

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 17.10   Speicherabbild mit einer Struktur mit unbenannten Lücken

Diese Abbildung stellt ein Vier-Byte-Alignment dar, wie es bei den meisten Systemen der Fall sein wird. Dabei entsteht eine Lücke von drei Byte (grau gefärbt), welche ungenutzt bleibt. Es wird hier auch vom »Padding« (Auffüllen, Polsterung) des Speichers gesprochen.


Hinweis   Dies ist übrigens auch der Grund, warum Sie Strukturen nicht direkt miteinander vergleichen können. Auch ein Low-Level-Vergleich, Byte für Byte, kann da nicht viel helfen, da dieser durch zufällig gesetzte Bits in den Löchern verfälscht sein könnte. In solch einem Fall müssen Sie sich mit einer eigenen Funktion, welche die einzelnen Strukturelemente miteinander vergleicht, selbst behelfen.


Viele Compiler besitzen daher einen speziellen Schalter, mit dem diese Lücke entfernt werden kann. Wobei ich gleich anmerken muss, dass dies nicht ANSI C-konform und Compiler-abhängig ist.

Mit dem Schalter

__attribut__

können dem Compiler mehrere Informationen zu einer Funktion, zu Variablen oder Datentypen übergeben werden. Um damit eine lückenlose Speicherbelegung zu erreichen, könnten Sie das Attribut packed verwenden.

Sollte dieser Schalter bei Ihrem Compiler nicht funktionieren, können Sie auch das Pragma pack verwenden:

#pragma pack(n)

Für n kann hier der Wert 1, 2, 4, 8 oder 16 angegeben werden. Je nachdem, welche Angabe Sie dabei machen, wird jedes Strukturelement nach dem ersten kleineren Elementtyp oder auf n Byte abgespeichert.

Beim Testen auf verschiedenen Systemen und unterschiedlichen Compilern gab es keine Probleme mit dem #pragma pack. Die Option __attribut__ hingegen wurde nicht von jedem Compiler erkannt. Wie Sie dabei vorgehen, müssen Sie letztendlich selbst herausfinden.

Hier das Beispiel dazu:

/* alignment2.c */
#include <stdio.h>
#include <stdlib.h>
/* Lässt sich dieses Listing nicht übersetzen,
 * entfernen Sie __attribute__((packed)) und
 * verwenden stattdessen #pragma pack(1)
 */
/* #pragma pack(1) */
struct speicher {
   char x;
   int z;
} __attribute__ ((packed));
int main(void) {
   struct speicher test;
   printf("%ld Bytes\n",sizeof(test));
   return EXIT_SUCCESS;
}

Damit benötigt die Struktur tatsächlich 5 Byte. Dies funktioniert bei manchen Compilern auch bei den enum-Aufzählungen:

/* alignment3.c */
#include <stdio.h>
#include <stdlib.h>
/* #pragma pack(1); */
enum{TRUE,FALSE}__attribute__ ((packed));
int main(void) {
   printf("%ld Bytes\n",sizeof(TRUE));
   return EXIT_SUCCESS;
}

Das Beispiel funktionierte beim Testen allerdings nur mit dem gcc-Compiler. In diesem Fall wird durch packed ein 1-Byte-Alignment angelegt. Das ist gegenüber den vier Bytes ohne packed beachtlich. Diese Werte können natürlich von System zu System unterschiedlich sein.


Hinweis   Natürlich müssen Sie sich auch im Klaren sein, dass hier zwischen Performance und Speicherplatz entschieden wird. Schließlich greifen Sie ja in die geschwindigkeitsoptimierte Speicherung des Betriebssystems ein.


Bei den Vorteilen, die mit packed oder dem Pragma pack erzielt werden, sollten die Nachteile beachtet werden. Wenn diese Daten (struct speicher) auf einem System mit fünf Bytes pro Struktur in einer Datei gespeichert werden, kann es passieren, dass diese Daten auf einem anderen System falsch angezeigt werden, weil das System vielleicht dort die Option packed nicht kennt und einfach ignoriert. Außerdem könnten Low-Level-Funktionen fehlschlagen, da sich die Daten wegen des Alignments nicht dort befinden, wo die Funktionen diese vermutet.

 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de