Forum: PC-Programmierung packed attribute bei struct


von Benedikt K. (benedikt)


Lesenswert?

Mit Hilfe eines structs zerlege ich den Header einer Datei in die 
einzelnen Werte. Leider richtet der Compiler die long Werte auf 4Byte 
Grenzen aus.  Gibt es bei MVC++ 6.0 irgendwas, um dem Compiler 
mitzuteilen, dass er dieses Struct möglichst unverändert lassen soll ?
Dass man das global einstellen kann, ist mir bekannt, ich möchte aber 
nur dieses eine struct packen.
Beim gcc Compiler geht das mit
_attribut_ ((packed))
Aber dies scheint eben nicht Standard zu sein.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

#pragma pack

heißt es bei MSVC.



#pragma pack( [ n] )

Specifies packing alignment for structure and union members. Whereas the 
packing alignment of structures and unions is set for an entire 
translation unit by the /Zp option, the packing alignment is set at the 
data-declaration level by the pack pragma. The pragma takes effect at 
the first structure or union declaration after the pragma is seen; the 
pragma has no effect on definitions.

When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each 
structure member after the first is stored on the smaller member type or 
n-byte boundaries. If you use #pragma pack without an argument, 
structure members are packed to the value specified by /Zp. The default 
/Zp packing size is /Zp8.

The compiler also supports the following enhanced syntax:

#pragma pack( [ [ { push | pop}, ] [  identifier, ] ] [ n ] )

This syntax allows you to combine program components into a single 
translation unit if the different components use pack pragmas to specify 
different packing alignments.

Each occurrence of a pack pragma with a push argument stores the current 
packing alignment on an internal compiler stack. The pragma’s argument 
list is read from left to right. If you use push, the current packing 
value is stored. If you provide a value for n, that value becomes the 
new packing value. If you specify an identifier, a name of your 
choosing, the identifier is associated with the new packing value.

Each occurrence of a pack pragma with a pop argument retrieves the value 
at the top of an internal compiler stack and makes that value the new 
packing alignment. If you use pop and the internal compiler stack is 
empty, the alignment value is that set from the command-line and a 
warning is issued. If you use pop and specify a value for n, that value 
becomes the new packing value. If you use pop and specify an identifier, 
all values stored on the stack are removed from the stack until a 
matching identifier is found. The packing value associated with the 
identifier is also removed from the stack and the packing value that 
existed just before the identifier was pushed becomes the new packing 
value. If no matching identifier is found, the packing value set from 
the command line is used and a level-one warning is issued. The default 
packing alignment is 8.

The new, enhanced functionality of the pack pragma allows you to write 
header files that ensure that packing values are the same before and 
after the header file is encountered:
1
/* File name: include1.h */
2
#pragma pack( push, enter_include1 )
3
/* Your include-file code ... */
4
#pragma pack( pop, enter_include1 )
5
/* End of include1.h */

In the previous example, the current pack value is associated with the 
identifier enter_include1 and pushed, remembered, on entry to the header 
file. The pack pragma at the end of the header file removes all 
intervening pack values that may have occurred in the header file and 
removes the pack value associated with enter_include1. The header file 
thus ensures that the pack value is the same before and after the header 
file.

The new functionality also allows you to use code, such as header files, 
that uses pack pragmas to set packing alignments that differ from the 
packing value set in your code:
1
#pragma pack( push, before_include1 )
2
#include "include1.h"
3
#pragma pack( pop, before_include1 )

In the previous example, your code is protected from any changes to the 
packing value that might occur in include.h.

von Simon K. (simon) Benutzerseite


Lesenswert?

Du kannst alternativ das Alignment in Structs auch in den ganz normalen 
Kompilierungs-Einstellungen ändern. (Eigenschaften von Projekt->Settings 
oder sowas)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das gilt dann aber für das gesamte Programm, was zu interessanten 
Nebenwirkungen führen kann, wenn mit Betriebssystem- oder anderen 
Libraries gearbeitet wird.
Bei Betriebssystemheaderdateien sollte man zwar ernsthaft annehmen, daß 
die durch entsprechende Verwendung von #pragma pack vor solchem Unfug 
geschützt sind, aber andere Headerdateien müssen nicht so sauber 
programmiert sein ...

von Simon K. (simon) Benutzerseite


Lesenswert?

Rufus t. Firefly wrote:
> Das gilt dann aber für das gesamte Programm, was zu interessanten
> Nebenwirkungen führen kann, wenn mit Betriebssystem- oder anderen
> Libraries gearbeitet wird.
> Bei Betriebssystemheaderdateien sollte man zwar ernsthaft annehmen, daß
> die durch entsprechende Verwendung von #pragma pack vor solchem Unfug
> geschützt sind, aber andere Headerdateien müssen nicht so sauber
> programmiert sein ...

Jup, das stimmt natürlich. Hast du ja auch nen langen Beitrag oben 
drüber geschrieben :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

s/geschrieben/zitiert/

von Simon K. (simon) Benutzerseite


Lesenswert?

Rufus t. Firefly wrote:
> s/geschrieben/zitiert/

Dann mal :wq

ums mal in VI-Syntax zu sagen ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.