2016-01-19 10 views
6

Consideriamo seguente frammento di codice:Pointer aritmetica sui tipi non-matrice

struct Blob { 
    double x, y, z; 
} blob; 

char* s = reinterpret_cast<char*>(&blob); 
s[2] = 'A'; 

Supponendo che sizeof (doppio) è 8, fa questo codice di attivazione comportamento indefinito?

+4

Questo non sarebbe nemmeno compilato senza un cast però. – dgross

+0

È questo C? In C++ questo non verrà compilato. – Bathsheba

+1

Questo non è legale C o C++, è necessario un cast. Una volta che hai un cast, questo è legale e ben definito. Ovviamente tutto può succedere se si tenta di accedere a blob.x in seguito. –

risposta

5

Citando N4140 (circa C++ 14):

3.9 Tipi [basic.types]

2 Per qualsiasi oggetto (diverso da un sotto-oggetto classe base) di banalmente copiabile digitare T, se l'oggetto contiene o meno un valore valido di tipo T, i byte sottostanti (1.7) che costituiscono l'oggetto possono essere copiati in un array di char o unsigned char. Se il contenuto dell'array di char o unsigned char viene copiato nell'oggetto, l'oggetto deve successivamente conservare il suo valore originale.

42) Utilizzando, ad esempio, le funzioni di libreria (17.6.1.2) std::memcpy o std::memmove.

3 Per qualsiasi tipo banalmente copiabile T, se due puntatori a T punto a distinte T oggetti obj1 e obj2, dove né obj1obj2 è un sotto-oggetto classe base, se si copiano i byte sottostanti (1.7) che compongono obj1 in obj2, obj2 deve successivamente contenere lo stesso valore di obj1. [Esempio: ...]

43) Utilizzando, ad esempio, le funzioni di libreria (17.6.1.2) std::memcpy o std::memmove.

Ciò, in linea di principio, consentono assegnazione direttamente s[2] se si prende il che una cessione ad s[2] è indirettamente richiesto di essere equivalente a copiando tutti qualche altro Blob in una matrice che avviene solo per essere a byte identici tranne per il terzo byte, e copiandolo nel tuo Blob: non stai assegnando a s[0], s[1], ecc. Per i tipi banalmente copiabili incluso char, equivale a impostarli sul valore esatto che hanno già, che inoltre non ha alcun osservabile effetto.

Tuttavia, se l'unico modo per ottenere s[2] == 'A' è di manipolazione della memoria, quindi un argomento valido potrebbe essere fatta anche che quello che stai copiando di nuovo nella vostra Blobnon è i byte sottostanti che componevano qualsiasi precedente Blob . In tal caso, tecnicamente, il comportamento non sarebbe definito dall'omissione.

Sospetto fortemente, in particolare dato "se l'oggetto contiene o meno un valore valido di tipo T" commento, che è previsto che sia consentito.

+0

I commenti non sono per discussioni estese; questa conversazione è stata [spostata in chat] (http://chat.stackoverflow.com/rooms/101136/discussion-on-answer-by-hvd-pointer-arithmetics-on-non-array-types). –

0

Il capitolo 3.10 della norma sembra consentire quello specifico caso, assumendo che "accedere al valore memorizzato" significa "leggere o scrivere", che non è chiaro.

3.10-10

Se un programma tenta di accesso il valore memorizzato di un oggetto attraverso un glvalue di diverso da uno dei seguenti tipi di comportamento è unde fi nita:

- (10.1) il tipo dinamico dell'oggetto,

- (10.2) una versione cv-qualificata del tipo dinamico dell'oggetto,

- (10.3) un tipo simile (come definita in 4.4) per il tipo dinamico dell'oggetto ,

- (10.4) un tipo che è il segno o tipo senza segno corrispondente al tipo dinamico del oggetto,

- (10.5) un tipo che è la firma o tipo senza segno corrispondente ad una versione cv-quali fi cata di tipo dinamico dell'oggetto,

- (10.6) un tipo di aggregato o unione che comprende uno dei tipi sopra indicati tra i suoi elementi o membri di dati non statici (compresi, ricorsivamente, un elemento o componente di dati non statica di una subaggregate o unione contenuta),

- (10.7) un tipo che è una (possibilmente cv-quali fi cato) tipo di classe di base di tipo dinamico dell'oggetto,

- (10,8) un tipo di carattere char o unsigned.