2012-06-21 21 views
6

Desidero che la dimensione di una struct C sia multiplo di 16 byte (16B/32B/48B/..). Non importa a quale dimensione arriva, deve essere solo multiplo di 16B. Come posso far rispettare il compilatore per farlo? Grazie.Allineamento delle dimensioni della struct

+4

Che cos'è il compilatore? – Joe

+1

Il titolo usa la parola allineamento, tuttavia il corpo della domanda parla della dimensione della struttura. Cosa vuoi veramente realizzare? E sono anche curioso del perché. –

+0

E qui c'è un articolo esistente che fornisce una soluzione che utilizza un'unione per eseguire il rilievo su una determinata dimensione. Comunque quella soluzione richiede la conoscenza della dimensione della struct [Size of Struct] (http://stackoverflow.com/questions/8705665/force-specific-struct-size-in-c), tuttavia ciò che dovresti fare è usare un calcolo della dimensione per l'array di caratteri come (sizeof (struct it)/16 + 1) * 16 piuttosto che una costante numerica. –

risposta

5

La dimensione di una struttura C dipenderà dai membri della struttura, i loro tipi e quanti di essi sono. Non c'è davvero un modo standard per forzare il compilatore a fare in modo che le strutture siano multiple di una certa dimensione. Alcuni compilatori forniscono un pragma che ti consentirà di impostare il limite di allineamento, tuttavia questa è davvero una cosa diversa. E potrebbe esserci qualcuno che avrebbe una tale impostazione o fornire un tale pragma.

Tuttavia, se si insiste su questo metodo sarebbe quello di fare l'allocazione della memoria della struct e per forzare l'allocazione di memoria per arrotondare alla prossima dimensione di 16 byte.

Quindi, se si ha una struttura come questa.

struct _simpleStruct { 
    int iValueA; 
    int iValueB; 
}; 

Quindi si potrebbe fare qualcosa come il seguente.

{ 
    struct _simpleStruct *pStruct = 0; 
    pStruct = malloc ((sizeof(*pStruct)/16 + 1)*16); 
    // use the pStruct for whatever 
    free(pStruct); 
} 

Che questo sarebbe fare è di spingere la dimensione fino alla prossima dimensione di 16 byte per quanto tu fossi interessato. Tuttavia, ciò che l'allocatore di memoria può o non può essere di darvi un blocco che è in realtà quella dimensione. Il blocco di memoria potrebbe effettivamente essere più grande della tua richiesta.

Se stai per fare qualcosa di speciale con questo, per esempio diciamo che stai andando a scrivere questa struttura in un file e vuoi conoscere la dimensione del blocco, allora dovresti fare lo stesso calcolo usato nel malloc() piuttosto che usare l'operatore sizeof() per calcolare la dimensione della struct.

Così la prossima cosa sarebbe quella di scrivere il proprio operatore proprio sizeof() utilizzando una macro come ad esempio.

#define SIZEOF16(x) ((sizeof(x)/16 + 1) * 16) 

quanto ne so non esiste un metodo affidabile per tirare la dimensione di un blocco allocato da un puntatore. Normalmente un puntatore avrà un blocco di allocazione di memoria che viene utilizzato dalle funzioni di gestione dell'heap della memoria che conterranno varie informazioni di gestione della memoria come la dimensione del blocco allocata che potrebbe essere effettivamente più grande della quantità di memoria richiesta. Tuttavia, il formato per questo blocco e dove si trova rispetto all'indirizzo di memoria effettivo fornito dipenderà dal tempo di esecuzione del compilatore C.

+0

Si dovrebbe [non eseguire il cast del valore restituito da 'malloc()', in C] (http://stackoverflow.com/a/605858/28169). – unwind

5

Questo dipende interamente dal compilatore e da altri strumenti poiché l'allineamento non è specificato in profondità nello standard ISO C (specifica che l'allineamento può verificarsi ai compilatori, ma non entra nei dettagli su come applicarlo).

Avrete bisogno di esaminare la roba attuazione specifiche per la vostra toolchain del compilatore. Può fornire uno #pragma pack (o align o qualche altra cosa) che è possibile aggiungere alla definizione della struttura.

Essa può anche fornire questo come un'estensione del linguaggio. Ad esempio, gcc consente di aggiungere attributi a una definizione, una delle quali controlla l'allineamento:

struct mystruct { int val[7]; } __attribute__ ((aligned (16))); 
11

Per Microsoft Visual C++:

#pragma pack(push, 16) 

struct _some_struct 
{ 
    ... 
} 

#pragma pack(pop) 

Per GCC:

struct _some_struct { ... } __attribute__ ((aligned (16))); 

Esempio:

#include <stdio.h> 

struct test_t { 
    int x; 
    int y; 
} __attribute__((aligned(16))); 

int main() 
{ 
    printf("%lu\n", sizeof(struct test_t)); 
    return 0; 
} 

compilato con gcc -o main main.c verrà emesso 16. Lo stesso vale per altri compilatori.

+1

Per gcc __attribute__ allineato, sta forzando la dimensione della struct a essere multiplo di 16B? O semplicemente garantisce che l'indirizzo iniziale della struttura sia allineato a 16B? –

+1

Sia l'indirizzo iniziale che la dimensione della struttura saranno allineati a 16B. Questo viene fatto per assicurare il corretto allineamento degli elementi dell'array di strutture. – Romeo

+0

Questo non è vero. La macro __attribute (aligned (x))) alloca la struct su un limite di x-byte e non ha nulla a che fare con la dimensione della struct http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc /Variable-Attributes.html –

3

Si potrebbe forse fare un doppio struct, avvolgendo lo struct reale in un secondo che può aggiungere padding:

struct payload { 
    int a; /*Your actual fields. */ 
    float b; 
    char c; 
    double d; 
}; 

struct payload_padded { 
    struct payload p; 
    char padding[16 * ((sizeof (struct payload) + 15)/16)]; 
}; 

Poi si può lavorare con la struct imbottita:

struct payload_padded a; 

a.p.d = 43.3; 

Naturalmente , puoi fare uso del fatto che il primo membro di una struttura inizia a 0 byte da dove inizia la struttura e considera un puntatore a struct payload_padded come se fosse un puntatore a un struct payload (perché lo è):

float d_plus_2(const struct payload *p) 
{ 
    return p->d + 2; 
} 

/* ... */ 

struct payload_padded b; 
const double dp2 = d_plus_2((struct payload *) &b); 
Problemi correlati