2012-07-08 17 views
33

Qual è la differenza tra sizeof e alignof?Qual è la differenza tra sizeof e alignof?

#include <iostream> 

#define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << '/' << alignof(T) << std::endl 

int main(int, char**) 
{ 
     SIZEOF_ALIGNOF(unsigned char); 
     SIZEOF_ALIGNOF(char); 
     SIZEOF_ALIGNOF(unsigned short int); 
     SIZEOF_ALIGNOF(short int); 
     SIZEOF_ALIGNOF(unsigned int); 
     SIZEOF_ALIGNOF(int); 
     SIZEOF_ALIGNOF(float); 
     SIZEOF_ALIGNOF(unsigned long int); 
     SIZEOF_ALIGNOF(long int); 
     SIZEOF_ALIGNOF(unsigned long long int); 
     SIZEOF_ALIGNOF(long long int); 
     SIZEOF_ALIGNOF(double); 
} 

stamperà

1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 4/4 8/8 8/8 8/8

Penso di non capire quale sia l'allineamento ...?

+16

provare di nuovo con le strutture anziché i tipi nativi. –

+1

'Restituisce l'allineamento in byte (una potenza integer di due) richiesto per qualsiasi istanza del tipo specificato' - http://en.cppreference.com/w/cpp/language/alignof. 'sizeof' fornisce solo le dimensioni, in byte, ovviamente. – chris

+1

Forse degno di nota - [sizeof è sempre un multiplo di alignof] (http://stackoverflow.com/questions/4637774/is-the-size-of-a-struct-required-to-be-an-exact-multiple -del-allineamento-di-tha) – Steve314

risposta

3

Il sizeof operator fornisce le dimensioni in byte di un tipo o istanza di un tipo.

Il alignof operator fornisce l'allineamento in byte richiesto per qualsiasi istanza del tipo specificato.

+6

cos'è "allineamento"? – user1494506

14

I due operatori fanno cose fondamentalmente diverse. sizeof indica la dimensione di un tipo (la quantità di memoria necessaria) mentre alignof indica a quanti byte deve essere allineato un tipo. Succede solo che le primitive che hai testato hanno un requisito di allineamento uguale alla loro dimensione (che ha senso se ci pensi).

pensare a cosa succede se si dispone di una struttura invece:

struct Foo { 
    int a; 
    float b; 
    char c; 
}; 

alignof(Foo) sarà tornare 4.

+1

perché? cosa significa 'alignof'? – user1494506

+1

@tskuzzy hai detto 'alignof (Foo)' restituirà 4. Ma dipende dall'ABI di destinazione. Quindi questo potrebbe essere vero su ia32 (x86) ma non su ARM, MIPS, PowerPC, ecc. – ydroneaud

+3

4 ??? Non capisco davvero il punto aggiuntivo – Offirmo

54

Bene, "memoria" è fondamentalmente una vasta gamma di byte. Tuttavia, le cose più grandi come gli interi hanno bisogno di più di 1 byte per memorizzarle - un valore a 32 bit, ad esempio, userebbe 4 byte consecutivi di memoria.

Ora, i moduli di memoria nel computer in genere non sono "byte"; sono anche organizzati con pochi byte "in parallelo", come blocchi di 4 byte.

Per una CPU, è molto più facile = più efficiente = migliori prestazioni di non "croce" tale blocco-confini quando si legge qualcosa di simile a un numero intero:

memory byte 0 1 2 3  4 5 6 7  8 9 10 11 
integer  goooood 
        baaaaaaaaad 

Questo è ciò che dice il "allineamento": un l'allineamento di 4 significa che i dati di questo tipo dovrebbero (o devono, dipende dalla CPU) essere memorizzati a partire da un indirizzo multiplo di 4.

L'osservazione che sizeof == alignof non è corretto; provare le strutture. Anche le strutture saranno allineate (perché i loro singoli membri devono finire sugli indirizzi corretti), ma le loro dimensioni saranno molto più grandi.

+14

- sebbene x86 faccia letture e scritture non allineate (lentamente ma correttamente) per la maggior parte delle cose, alcune architetture richiedono che tutte le operazioni siano allineate, e anche in x86 ci sono alcuni casi speciali che devono essere allineati (SIMD istruzioni, penso). – Steve314

+0

grazie! ora lo ottengo – user1494506

+2

@ user1494506 - Se questa o qualsiasi altra risposta risponde correttamente alla tua domanda, * considera * la marcatura corretta. (Naturalmente questo è * puramente la tua scelta *. Non essere forzato ad accettare risposte perché la gente lo dice (ad esempio, come sto dicendo ora) :) – ArjunShankar

5

Il valore di alignof è uguale al valore di sizeof per i tipi di base.

La differenza si trova nei tipi di dati definiti utilizzati come l'utilizzo di struct; per un es.

typedef struct { int a; double b; } S; 
//cout<<alignof(s);        outputp: 8; 
//cout<<sizeof(S);        output: 12; 

quindi il valore sizeof è la dimensione totale richiesta per il tipo di dati specificato; e il valore di allineamento è il requisito di allineamento dell'elemento più grande nella struttura.

Uso di alignof: alloca memoria su un particolare limite di allineamento.

6

Vecchia domanda (anche se non contrassegnata come risposta ..) ma ho pensato che questo esempio faccia la differenza un po 'più esplicita oltre alla risposta di Christian Stieber. Anche la risposta di Meluha contiene un errore come sizeof (S) di uscita è 16 non 12.

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary 
//   | 8 bytes | | 8 bytes | | 8 bytes | 
struct Bad { char c;  double d;  int i;  }; 
cout << alignof(Bad) << " " << sizeof(Bad) << endl; // 8 24 

//    | 8 bytes | | 8 bytes |  
struct Good { double d;  int i; char c;   }; 
cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16 

Essa dimostra anche che è migliori membri ordinazione di dimensioni con più basso (doppio in questo caso), come gli altri membri sono vincolato da quel membro.

2

per le risposte fornite, sembra che ci sia una certa confusione su ciò che allineamento è in realtà. La confusione probabilmente deriva dal fatto che ci sono 2 tipi di allineamento.

1. Gli allineamento

Questa è una misura qualitativa che definisce quanto grande un'istanza è in numero di byte per uno specifico ordinamento dei membri all'interno il tipo di struttura/classe. Generalmente, i compilatori possono compattare istanze di struttura/classe se i membri sono ordinati in base alla loro dimensione in ordine decrescente (vale a dire il più grande per primo, i membri più piccoli durano) all'interno della struttura. Prendere in considerazione:

struct A 
{ 
    char c; float f; short s; 
}; 

struct B 
{ 
    float f; short s; char c; 
}; 

Entrambe le strutture contengono esattamente le stesse informazioni. Per il bene di questo esempio; il tipo float richiede 4 byte, il tipo breve accetta 2 e il carattere accetta 1 byte. Tuttavia, la prima struttura A ha membri in ordine casuale, mentre la seconda struttura B ordina i membri in base alla loro dimensione in byte (questo potrebbe essere diverso su certe architetture, sto assumendo l'architettura Intel x86 intel con un allineamento di 4 byte in questo esempio). Consideriamo ora le dimensioni delle strutture:

printf("size of A: %d", sizeof (A)); // size of A: 12; 
printf("size of B: %d", sizeof (B)); // size of B: 8; 

Se ci si aspetterebbe la dimensione per essere 7 byte, si sarebbe supponendo che i membri sono imballato nella struttura con un allineamento di 1 byte. Mentre alcuni compilatori lo consentono, in generale la maggior parte dei compilatori usa allineamenti a 4 o anche 8 byte a causa di motivi storici (la maggior parte della CPU lavora con registri generici DWORD (parola doppia) o QWORD (quadricromia).

Ci sono 2 meccanismi di imbottitura al lavoro per ottenere l'imballaggio.

  1. Innanzitutto, ogni membro che ha una dimensione di byte inferiore al byte-allineamento è 'fusa' con l'elemento successivo (s) se la dimensione in byte risultante è minore o uguale al byte-allineamento. Nella struttura B, i membri s e c possono essere uniti in questo modo; la loro dimensione combinata è di 2 byte per s + 1 byte per c == 3 byte < = 4 byte di allineamento. Per la struttura A, non può verificarsi tale fusione e ogni membro consuma effettivamente 4 byte nell'imballaggio della struttura.

  2. La dimensione totale della struttura viene nuovamente riempita in modo che la struttura successiva possa iniziare al limite di allineamento. Nell'esempio B il numero totale di byte sarebbe 7. Il prossimo limite di 4 byte si trova al byte 8, quindi la struttura viene riempita con 1 byte per consentire allocazioni di array come una sequenza di istanze strette.

Si noti che Visual C++/GCC consente diversi allineamenti di 1 byte, 2 e multipli superiori di 2 byte.Comprendi che questo funziona contro la capacità del tuo compilatore di produrre codice ottimale per la tua architettura. Infatti, nel seguente esempio, ciascun byte verrebbe letto come un singolo byte utilizzando un'istruzione a byte singolo per ciascuna operazione di lettura. In pratica, l'hardware recupera comunque l'intera riga di memoria che contiene ogni byte letto nella cache ed esegue l'istruzione 4 volte, anche se i 4 byte si trovano nello stesso DWORD e potrebbero essere caricati nel registro della CPU in 1 istruzione.

#pragma pack(push,1) 
struct Bad 
{ 
    char a,b,c,d; 
}; 
#pragma pack(pop) 

2. allineamento Allocation

Ciò è strettamente legato al meccanismo 2a imbottitura spiegato nella sezione precedente, tuttavia, un allineamenti llocation può essere specificata in varianti di malloc/memalloc funzioni di allocazione. Quindi, è possibile allocare un oggetto a un limite di allineamento diverso (tipicamente più alto di 2) rispetto a quanto suggerito dall'allineamento dei byte del tipo di struttura/oggetto.

size_t blockAlignment = 4*1024; // 4K page block alignment 
void* block = malloc(sizeof(T) * count, blockAlignment); 

Il codice inserirà il blocco di istanze di conteggio di tipo T su indirizzi che terminano su multipli di 4096.

La ragione per usare tali allineamenti di assegnazione vengono nuovamente puramente architettonico. Ad esempio, leggere e scrivere blocchi da indirizzi allineati alla pagina è più veloce perché l'intervallo di indirizzi si adatta perfettamente ai livelli della cache. Gli intervalli suddivisi su diverse "pagine" cancellano la cache quando attraversano il limite della pagina. Supporti diversi (architetture di bus) hanno diversi modelli di accesso e possono trarre vantaggio da diversi allineamenti. Generalmente, gli allineamenti di 4, 16, 32 e 64 K non sono rari.

Problemi correlati