PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C Syntax Nr.102 - Bitgefrickel und Struct Alignment


mekakic
2009-06-30, 15:07:21
Hi,

ich gucke mich gerade um, wie man Nachrichtenpakete komfortabel in C zusammenpacken und organisieren kann und bin über etwas gestolpert, was ich nicht kannte.

Normalerweise kann man logisch und hierarchisch Nachrichten ja sehr gut modellieren, in dem man sich ein Struct nimmt und da alles so organisiert, wie man es haben möchte. Das funktioniert aber normalerweise nicht als Nachrichtenformat, da man nicht sicher weiß, was der Compiler auf der einen Seite dem Typ für ein Datenalignment gegeben hat und ich kenne bisher keinen Weg einer bestimmten Struktur sicher ein Datenaligment auf 1-Byte Größen zu geben (wenn da jemand was kennt...).

Wenn ich allerdings sowas mache:
union byte_u
{
struct bits_s
{
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} bitmask;
uint8_t byte;
};
Diese Schreibweise mit dem Doppelpunkt und der Angabe wieviel Bit ein Feld belegt habe ich zum ersten Mal gesehen. Habe ich das so zu verstehen, daß mit der ersten Variable der Speicherplatz in einem Struct bestimmt wird und man kann weitere Anhängen, die dann allmählich diese 8Bit füllen? Also wenn ich b7 weglasse braucht das Struct immernoch 1Byte Speicher (jetzt unabhängig von der union)? Und über 8Bit hinaus werden dann eben die nächsten uint8, uint16, uint32, uint64 verwendet, je nachdem welchen Typ das nächste Bitfeld im Struct hat?

Funktioniert das überall, auch über Compilergrenzen, CPUs etc. in C89/C90? In so einem Struct wo die Bitfelder über mehrere Grenzen hinausgehen liegt dann ja wohl kein Alignment an, oder? Kann Ich das auch für beliebige Typen verwenden? Ich gebe einem Struct im Struct einfach eine Größe an und die braucht es fortan? Oder müssen die folgenden immer vom gleichen Typ sein?
:confused:

Coda
2009-06-30, 15:44:11
b1 = 1. Bit, b2 = 2. Bit, usw. von "uint8_t byte". Das ": 1" bedeutet, dass nur ein Bit für die jeweilige Variable verwendet wird.

Schau nach was "union" bedeutet und du verstehst es.

maximAL
2009-06-30, 19:13:55
und ich kenne bisher keinen Weg einer bestimmten Struktur sicher ein Datenaligment auf 1-Byte Größen zu geben (wenn da jemand was kennt...).

Gibt es, aber nur compiler -u. plattformabhängig. Beim gcc z.B. so (http://tuxsudh.blogspot.com/2005/05/structure-packing-in-gcc.html)

ManuelCalavera
2009-06-30, 23:39:28
Ich weiss zwar nicht wies mir der alignierung aussieht, aber für Nachrichtenpakete eignen sich auch die protocol buffers von google (http://code.google.com/p/protobuf/)...

pest
2009-07-01, 00:11:10
#pragma pack(push,1)
...
#pragma pack(pop)


hier von microsoft ein header-file (pshpack1.h)



/*++

Copyright 1995 - 1998 Microsoft Corporation

Module Name:

pshpack1.h

Abstract:

This file turns 1 byte packing of structures on. (That is, it disables
automatic alignment of structure fields.) An include file is needed
because various compilers do this in different ways. For Microsoft
compatible compilers, this files uses the push option to the pack pragma
so that the poppack.h include file can restore the previous packing
reliably.

The file poppack.h is the complement to this file.

--*/

#if ! (defined(lint) || defined(_lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 ) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push)
#endif
#pragma pack(1)
#else
#pragma pack(1)
#endif
#endif // ! (defined(lint) || defi

SimonX
2009-07-01, 10:04:51
@mekakic

Die Bit-Felder die du in der Struktur/Union definiert hast werden (compiler-abhängig) in einen Int-Type zusammen gefasst.

Das mit der union klappt nur wenn der type, der für bit-felder benutzt wird, LSB first codiert ist. Und das ist platform-abhängig