2013-07-24 22 views
31

in C/C++ (Io parto dal presupposto che siano gli stessi in questo senso), se ho il seguente:struct allineamento C/C++

struct S { 
    T a; 
    . 
    . 
    . 
} s; 

è la seguente garantita per essere vero?

(void*)&s == (void*)&s.a; 

O in altre parole, non v'è alcun tipo di garanzia che non ci sarà alcuna imbottitura prima il primo membro?

+1

Non sono uguali a questo proposito –

+3

@MooingDuck: Beh, dipende da cosa '' ... 'è. Per la stessa definizione di struct, C++ lo tratterà allo stesso modo di C (le strutture C soddisfano sempre il requisito standard * di C++ *). –

risposta

44

In C, sì, sono lo stesso indirizzo. Semplice e diretto.


In C++, no, non sono lo stesso indirizzo. Le classi base possono (e io sospetto, lo faccio) venire prima di tutti i membri e le funzioni dei membri virtuali di solito aggiungono dati nascosti alla struttura da qualche parte. Ancora più confuso, un compilatore C++ può anche riorganizzare i membri a volontà, a meno che la classe sia un tipo di layout standard (anche se non so che qualsiasi compilatore lo faccia)

Infine, se la struttura C++ è composta da standard tipi di layout, non contiene classi base né funzioni virtuali e tutti i membri hanno la stessa visibilità e possibilmente altre limitazioni che ho dimenticato, quindi ricade sulle regole C e richiede che il primo membro sia allo stesso indirizzo del oggetto stesso.

§ 9,2/7

Una classe standard la layout è una classe che:
- ha alcun membri dati non statici della classe tipo non standard layout (o array di tali tipi) o riferimento,
- non ha funzioni virtuali (10.3) e classi base virtuali (10.1),
- ha lo stesso controllo di accesso (Articolo 11) per tutti i membri di dati non statici,
- ha non Standard- classi di base del layout,
- non ha membri di dati non statici nella classe più derivata e al massimo una classe base con membri dati non statici o senza classi base con membri dati non statici e
- non ha classi base dello stesso tipo del primo membro dati non statico .

§ 9.2/20

Un puntatore a un oggetto struct standard di layout, opportunamente convertito utilizzando un reinterpret_cast, punti al suo membro iniziale (o se tale elemento è un campo di bit, quindi all'unità in cui risiede) e viceversa. [Nota: potrebbe pertanto esserci un padding senza nome all'interno di un oggetto struct con layout standard, ma non all'inizio, come necessario per ottenere l'allineamento appropriato. -end note]

+0

"standard-layout class" è anche noto come POD ("plain old data type"), e puoi verificarlo usando std :: is_pod. – marcinj

+10

@marcin_j: No. POD richiede sia * layout standard * sia * costruzione banale/copia/distruzione *. Una classe può avere costruttori e distruttori non predefiniti e altri membri speciali ed essere ancora * layout standard *. –

+0

grazie per il chiarimento, vedo che è possibile utilizzare std :: is_standard_layout per verificare se tale confronto è corretto. – marcinj

16

Sì, lo è.

È garantito che non ci sia riempimento prima del primo membro della struct in C e in C++ (se è un POD).

C citazione: "Ci possono essere imbottitura senza nome all'interno di un oggetto struttura, ma non al suo inizio"

(C11, 6.7.2.1p15)

C++ preventivo:

(C++ 11, 9.2p20) "Ci potrebbe pertanto imbottitura senza nome di un oggetto struct standard di layout, ma non al suo inizio, come necessario per raggiungere opportuno allineamento "

+6

In C++ è garantito solo se si tratta di un POD. –

+0

@ n.m. aggiunto un preventivo per C++ e una menzione per POD. Grazie – ouah

+0

@ n.m. Se cos'è un POD? La struttura 'S' o il membro' T'? – baruch