Domanda

è la seguente conversione sicura?

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

Non penso che la conversione di cui sopra nel ciclo for è sicuro (penso che dipende dalla piattaforma). Perfavore, correggimi se sbaglio. Sono sorpreso, perché il codice viene compilato senza dare alcun avviso anche quando compilato utilizzando le opzioni -Wall -pedantic in gcc.

È stato utile?

Soluzione

Questa cosa ha la possibilità di essere legale per una e una sola ragione: l'oggetto array int 2D viene reinterpretato come un array di oggetti char. Mentre nella memoria generale caso reinterpretazione porta ad un comportamento indefinito, le specifiche del linguaggio permette esplicitamente "serie di [unsigned firmati /] char" reinterpretazioni di oggetti di qualsiasi tipo.

Tuttavia, un problema di sicurezza formale, è ancora lì. Il linguaggio non garantisce che qualsiasi modello di bit è un valore valido di tipo char. Il tentativo di leggere la memoria reinterpretata attraverso tipo char può teoricamente causare un comportamento indefinito se incontra rappresentazione trappola per char. Al fine di essere al sicuro qui è necessario utilizzare il tipo unsigned char, che è l'unico tipo che non ha rappresentazioni trappola. Naturalmente, una piattaforma con un char intrappolamento può essere chiamato in modo sicuro "esotico".

Nel frattempo, il vostro sizeof(a + 1) non sembra avere alcun senso. a + 1 è un'espressione di tipo int *. Perché ci si vuole utilizzare la dimensione del puntatore per incrementare il valore del x in questo caso non è chiaro per me. Cosa stavi cercando di raggiungere?

Per quanto riguarda l'assenza di avvertimenti ... Vorrei non aspettatevi il compilatore di emettere eventuali avvisi qui. GCC avverte spesso di tipo-gioco di parole (aka reinterpretazione della memoria), ma dal momento che reinterpretazioni char sono esplicitamente autorizzati (come ho detto sopra), non c'è nessun avvertimento qui. Inoltre, cast espliciti di solito tendono a sopprimere eventuali avvisi, in quanto sono un modo per dire al compilatore che non vuole realmente fare qualcosa a prescindere da come sbagliato e / o pericolosa che potrebbe essere.

Altri suggerimenti

un cast di qualsiasi tipo puntatore a char * è esplicitamente consentito dal linguaggio C. quindi la maggior parte di questo è bene.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

La prima parte è soddisfacente x = (char*)&b[0]; stabilisce un puntatore char all'inizio dell'array. Il test è anche bene x <= (char *)&b[9][9] sarà vero finché punti x all'interno della matrice.

x += sizeof(a+1) è la parte incerto. Sulla maggior parte delle architetture di CPU a 32 bit sizeof (int *) solo accade di essere lo stesso di sizeof (int), in modo da questo codice sarà probabilmente lavoro , ma solo per caso.

Sono sicuro che ciò che si intendeva era x += sizeof(a[0]) o x += sizeof(b[0]), ma dal momento che il codice in realtà ha fatto ciò che era destinato, nessuno notato il bug.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top