Equivalente di Visual C ++ di G__’s __attribute__ ((__packed__))

Per alcuni compilatori, esiste un identificatore di imballaggio per le strutture, ad esempio:

 Il compilatore ARM RealView ha "__packed"
 Gnu C Compiler ha "__attribute__ ((__packed__))"
 Visual C ++ non ha equivalenti, ha solo il "#pragma pack (1)"

Ho bisogno di qualcosa che possa essere inserito nella definizione della struttura .

Qualche informazione / hack / suggerimento? TIA …

Non conosco un modo shiny per farlo, ma potresti fare qualcosa di orribile come questo:

 #include "packed.h" struct Foo { /* members go here */ } PACKED; #include "endpacked.h" 

Quindi per MSVC, packed.h:

 #define PACKED #pragma pack(push,1) 

endpacked.h

 #pragma pack(pop) #undef PACKED 

Per gcc, packed.h:

 #define PACKED __attribute__ ((__packed__)) 

endpacked.h:

 #undef PACKED 

Fondamentalmente, l’imballaggio è troppo dipendente dalla piattaforma. Supponiamo che la struttura compressa contenga al suo interno campi a 8 bit e consideri alcuni sistemi con un byte a 16 bit. Non può avere una struttura che rappresenti i tuoi dati solo con il packing: dovresti sapere come i byte da 8 bit vengono convertiti in byte da 16 bit quando vengono trasferiti tra i due sistemi. La struttura sulla macchina a 16 bit potrebbe aver bisogno di bitfield, nel qual caso dovresti sapere come li mette in atto l’implementazione.

Quindi, se il codice è destinato a essere generalmente portatile, potresti semplicemente dover definire qualsiasi struttura di cui hai bisogno in una sezione specifica della piattaforma del tuo file di intestazione. O meglio, strutturare il codice in modo che una porta futura possa farlo se necessario.

È ansible definire PACK come questo per GNU gcc

 #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) 

e così per Visual C ++:

 #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) 

E usalo in questo modo:

 PACK( struct myStruct { int a; int b; }); 

So che questa domanda è vecchia ora, ma credo che ci sia una soluzione migliore di quelle pubblicate in precedenza. Dopo tutto, è ansible inserire il pragma nel caso MSVC nella riga della dichiarazione della struttura. Considera quanto segue:

 #ifdef _MSC_VER # define PACKED_STRUCT(name) \ __pragma(pack(push, 1)) struct name __pragma(pack(pop)) #elif defined(__GNUC__) # define PACKED_STRUCT(name) struct __attribute__((packed)) name #endif 

Quindi questo può essere usato in questo modo:

 typedef PACKED_STRUCT() { short a; int b } my_struct_t; PACKED_SRUCT(my_other_struct) { short a; int b }; 

eccetera.

La chiave qui è che l’uso di __pragma deve essere solo attorno alla riga di dichiarazione della struct. Questo deve includere il nome della struct se ne viene fornito uno, quindi il nome è un parametro della macro. Ovviamente, è facile estendere a enum / class, che lascerò come esercizio al lettore!

Il programma di test sulla documentazione MSDN della confezione è utile per verificarlo.

MODIFICARE

Nei miei test stavo usando Intel Compiler su Windows. Utilizzando icl.exe questo approccio funziona senza problemi, ma con il compilatore Microsoft (cl.exe) non lo fa (testato con il 2010 e il 2013).

Un’altra soluzione, a seconda di quali compilatori è necessario supportare, è notare che GCC ha supportato il pragma di imballaggio in stile Microsoft almeno dalla versione 4.0.4 (la documentazione online è disponibile su gnu.org per le versioni 3.4.6 e 4.0.4 – i pragma non sono descritti nel primo e sono nel secondo). Questo ti permette di usare #pragma pack(push,1) prima di una definizione della struttura e #pragma pack(pop) dopo la definizione e verrà compilato in entrambi.

Puoi farlo al contrario, dal momento che GCC supporta i pragmi relativi al pacchetto VC ++. Guarda qui per ulteriori informazioni.

Estratto…

Per compatibilità con i compilatori Microsoft Windows, GCC supporta un insieme di direttive #pragma che modificano l’allineamento massimo dei membri delle strutture (diversi dai bitfield a larghezza zero), i join e le classi successivamente definiti. Il valore n riportato sotto è sempre richiesto per essere una piccola potenza di due e specifica il nuovo allineamento in byte.

#pragma pack(n) imposta semplicemente il nuovo allineamento.

#pragma pack() imposta l’allineamento a quello che era -fpack-struct[=] quando la compilazione è iniziata (vedi anche l’opzione della riga di comando -fpack-struct[=] vedi Opzioni di Code Gen).

#pragma pack(push[,n]) spinge l’impostazione di allineamento corrente su uno stack interno e quindi imposta facoltativamente il nuovo allineamento.

#pragma pack(pop) ripristina l’impostazione di allineamento a quella salvata nella parte superiore dello stack interno (e rimuove quella voce dello stack).

Si noti che #pragma pack([n]) non influenza questo stack interno; quindi è ansible avere #pragma pack(push) seguito da più istanze di #pragma pack(n) e finalizzato da un singolo #pragma pack(pop) .

Alcuni obiettivi, ad esempio i386 e powerpc, supportano ms_struct #pragma che espone una struttura come __attribute__((ms_struct)) .

#pragma ms_struct on triggers il layout per le strutture dichiarate.

#pragma ms_struct off distriggers il layout delle strutture dichiarate.

#pragma ms_struct reset torna al layout predefinito.

Perché hai bisogno di qualcosa da fare nella struttura?

Penso che #pragma pack(1) sia lo stesso, o mi manchi qualcosa?

Puoi farlo:

 struct Foo { #pragma pack(push, 1) int Bar; #pragma pack(pop) }; 

Ma sembra brutto.