2013-07-24 23 views
31

w C/C++ (jestem przy założeniu, że są takie same w tym zakresie), jeśli mam następujące:struct wyrównanie C/C++

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

jest następujący gwarancją prawda?

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

Lub innymi słowy, czy istnieje jakiś rodzaj gwarancji, że nie będzie wyściółka przed pierwszym członkiem?

+1

Nie są one takie same pod tym względem –

+3

@MooingDuck: Cóż, to zależy od tego, czym jest '...'. Dla tej samej definicji struktury, C++ potraktuje ją w taki sam sposób, jak struktury C (C zawsze spełniają wymagania standardowego układu C++ *). –

Odpowiedz

44

W języku C, tak, są one tym samym adresem. Prosty i prosty.


W języku C++ nie, nie są one tym samym adresem. Klasy podstawowe mogą (i podejrzewam, że robię) przychodzą przed wszystkimi członkami, a funkcje wirtualnych elementów zwykle dodają gdzieś ukryte dane do struktury. Jeszcze bardziej mylące, kompilator C++ może również dowolnie zmieniać układy członków, chyba że klasa jest standardowym typem układu (choć nie wiem, że robi to dowolny kompilator)

Wreszcie, jeśli struktura C++ składa się ze standardu typy układów:, nie zawiera klas bazowych ani funkcji wirtualnych, a wszyscy członkowie mają tę samą widoczność i być może inne ograniczenia, o których zapomniałem, , następnie powraca na zasadach C i wymaga, aby pierwszy członek był pod tym samym adresem, co sam obiekt.

§ 9,2/7

Klasa standardowego układu jest klasa:
- nie ma nie-statycznych pól grupy typu nie-standardowego układu (lub szeregu takich typów) lub odniesienie,
- nie ma funkcji wirtualnych (10.3) i żadnych wirtualnych klas bazowych (10.1),
- ma tę samą kontrolę dostępu (Rozdział 11) dla wszystkich niestatycznych elementów danych,
- nie ma żadnych niestandardowych klasa podstawowa układu,
- albo nie ma żadnych statycznych elementów danych w większości klas pochodnych i co najwyżej jednej klasy bazowej z niestatycznymi elementami danych lub bez klas podstawowych z niestatycznymi elementami danych i
- nie ma klas podstawowych tego samego typu, co pierwszy niestatyczny element danych .

§ 9.2/20

Wskaźnik do struct obiektu standardowego układu, odpowiednio przekształcone za pomocą reinterpret_cast wskazuje na początkowej elementu (lub gdy element jest bitowe pole, a następnie do jednostki, w której się ona znajduje) i wzajemnie. [Uwaga: Może istnieć nienazwane wypełnienie wewnątrz obiektu strukturalnego o standardowym układzie, ale nie na jego początku, jeśli jest to konieczne do uzyskania odpowiedniego wyrównania. -end note]

+0

"Standardowy układ klasy" jest również znany jako POD ("zwykły stary typ danych"), i można go zweryfikować za pomocą std :: is_pod. – marcinj

+10

@marcin_j: Nr POD wymaga zarówno * standardowego układu * i * trywialnej konstrukcji/kopiowania/niszczenia *. Klasa może mieć niedomyślne konstruktory i destruktory oraz inne specjalne elementy i nadal może być * standardowym układem *. –

+0

dziękuję za wyjaśnienia, widzę, że można użyć std :: is_standard_layout , aby sprawdzić, czy takie porównanie jest poprawne. – marcinj

16

Tak, jest.

Jest zagwarantowane, że nie ma padding przed pierwszym członkiem struct w C i C++ (jeśli jest to POD).

C cytuję: "Nie może być bezimienny wyściółka wewnątrz struktury obiektu, ale nie na jego początku"

(C11, 6.7.2.1p15)

C++ cytat:

(C++ 11, 9.2p20) „Nie może być zatem nienazwany wyściółka wewnątrz struct obiektu standardowego układu, ale nie na jego początku, jak to konieczne, aby osiągnąć właściwe wyrównanie "

+6

W C++ jest to zagwarantowane tylko wtedy, gdy jest to POD. –

+0

@ n.m. dodano wycenę C++ i wzmiankę o POD. Dzięki – ouah

+0

@ n.m. Jeśli jest to POD? Struktura 'S' lub członek' T'? – baruch