2015-11-23 28 views
11

In this answer, int8_t* viene utilizzato per (byte) aritmetica dei puntatori:C++ offsetof char * aritmetica

std::size_t offset = offsetof(Thing, b); 
Thing* thing = reinterpret_cast<Thing*>(reinterpret_cast<int8_t*>(ptr) - offset); 

ho sempre usato char* in passato, ma i commenti sono davvero confusa, e nessuno ha risposto, così ho ha postato questa domanda separata.

È valido char* e il modo preferito di eseguire questi calcoli?

risposta

2

È must uso char*: il comportamento sull'utilizzo di un reinterpret_cast con int8_t* su un puntatore a qualcosa che non è un int8_t è indefinita. La trasmissione a char* può essere vista come un'eccezione alla regola.

Pre C++ 14, char può essere un complemento di tipo 1 con intervallo da -127 a +127. int8_t deve essere il complemento a 2. Perfino C++ 14 e successivi, non riesco a capire perché i tipi sono correlati: char può ancora essere un tipo firmato o non firmato.

+0

Per quanto riguarda le dimensioni del puntatore, ho pensato che tutti i puntatori agli oggetti avessero le stesse dimensioni in C++. Non è garantito? Ma qualunque sia la risposta, l'aritmetica del puntatore è influenzata da 'sizeof (T)', non 'sizeof (T *)'. In ogni caso, il punto su stand aliasing. –

+0

Il tuo ultimo punto è corretto: la sizeof (*) non è rilevante quindi l'ho rimossa perché indebolisce solo la risposta. Per quanto riguarda il primo punto, non riesco a capire perché i riferimenti agli oggetti siano rilevanti. Abbiamo solo i POD qui. – Bathsheba

+1

Nessuno del primo paragrafo è vero. 'uint8_t' in effetti non fa parte dell'autorizzazione speciale nella regola di aliasing, ma il puntatore non viene usato per punire il tipo qui, solo per l'aritmetica del puntatore. Le regole per l'aritmetica dei puntatori sono piuttosto più permissive e richiedono solo che l'allineamento sia appropriato e l'aritmetica non ti porta al di fuori dello stesso oggetto completo .... e non ci sono permessi speciali per 'char *' lì. –