2016-09-12 37 views
6

Given agregat struct/klasy w której każda zmienna członkiem jest tego samego typu danych:Czy to ważne, aby rzucić wskaźnik do struct do wskaźnika tablicy

struct MatrixStack { 
    Matrix4x4 translation { ... }; 
    Matrix4x4 rotation { ... }; 
    Matrix4x4 projection { ... }; 
} matrixStack; 

Jak ważne jest to, aby rzucić go do tablicy jego członkowie? na przykład

const Matrix4x4 *ptr = reinterpret_cast<const Matrix4x4*>(&matrixStack); 
assert(ptr == &matrixStack.translation); 
assert(ptr + 1 == &matrixStack.rotation); 
assert(ptr + 2 == &matrixStack.projection); 
auto squashed = std::accumulate(ptr, ptr + 3, identity(), multiply()); 

Robię to dlatego, że w większości przypadków muszą nazwie dostępu użytkownika dla jasności, podczas gdy w niektórych innych przypadkach trzeba przekazać tablicę do innego API. Używając reinterpret_cast, mogę uniknąć alokacji.

+0

Moje zrozumienie jest, że za pomocą rezultat gipsie, że nie zostanie skompilowany z wyjątkiem jeśli używanie reinterpret_cast prawie zawsze ryzykuje niezdefiniowane zachowanie. Ten szczególny przypadek prawdopodobnie będzie działał zgodnie z przeznaczeniem (chyba że twój kompilator przejdzie do wyrównania strukturalnego, aby członkowie Matrix4x4 nie byli w pełni przylegający do pamięci), ale wciąż nie jest gwarantowany przez standard. – antred

+0

Może działać, może nie, zależy od rzeczywistego rozmiaru i ustawień wyrównania danych Matrix4x4. –

+0

Struktury mogą mieć dopełnienie, gdy [tablice nigdy nie mają dopełnienia] (https://stackoverflow.com/questions/1066681/can-c-arrays-contain- wyściełanie między elementami). – sashoalm

Odpowiedz

3

Obsada nie jest wymagana do pracy według normy.

Jednakże, można dokonać za pomocą kodu bezpieczne statyczne twierdzi, że uniemożliwi to od kompilacji jeśli założenia są łamane:

static_assert(sizeof(MatrixStack) == sizeof(Matrix4x4[3]), "Size mismatch."); 
static_assert(alignof(MatrixStack) == alignof(Matrix4x4[3]), "Alignment mismatch."); 
// ... 
const Matrix4x4* ptr = &matrixStack.translation; 
// or 
auto &array = reinterpret_cast<const Matrix4x4(&)[3]>(matrixStack.translation); 
+1

Czy nie masz na myśli '==' pomiędzy dwoma argumentami 'sizeof' /' alignof'? –

+0

@AaronMcDaid Czytasz mój umysł, naprawiony! –

+0

I może dodać czek, który 'offsetof (MatrixStack, tłumaczenie) == 0'. Czy pierwszy element ma zawsze zerową wartość? Moglibyśmy sprawdzić, czy pozostali dwaj członkowie mają oczekiwane przesunięcia. –