Pregunta

Es la siguiente conversión segura?

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);

No creo que la conversión anterior en el bucle for es seguro (creo que es dependiente de la plataforma). Por favor, corríjame si estoy equivocado. Me sorprende debido a que el código se compila sin dar ninguna advertencia, incluso cuando se compila utilizando las opciones -Wall -pedantic en gcc.

¿Fue útil?

Solución

Todo esto tiene la oportunidad de ser legal para una y sólo una razón: el objeto de matriz 2D int se reinterpreta como una matriz de objetos char. Si bien en la memoria general caso reinterpretación conduce a un comportamiento indefinido, la especificación del lenguaje permite explícitamente "matriz de [unsigned firmados /] char" reinterpretaciones para objetos de cualquier tipo.

Sin embargo, un problema formal de la seguridad sigue estando ahí. El idioma no garantiza que cualquier patrón de bits es un valor válido del tipo char. Su intento de leer la memoria reinterpretado a través de tipo char teóricamente puede causar un comportamiento indefinido si encuentra la representación trampa para char. Con el fin de estar a salvo aquí hay que utilizar el tipo de unsigned char, que es el único tipo que no tiene representaciones trampa. Por supuesto, una plataforma con una char atrapamiento se puede llamar de forma segura "exótico".

Mientras tanto, su sizeof(a + 1) no parece tener ningún sentido. a + 1 es una expresión de tipo int *. ¿Por qué te gustaría usar el tamaño del puntero para incrementar su valor x en este caso no es claro para mí. ¿Qué estaba tratando de lograr?

En cuanto a la ausencia de advertencias ... Yo no esperaría que el compilador emitió ningún aviso aquí. GCC menudo advierte sobre el tipo-juegos de palabras (también conocido como reinterpretación de la memoria), pero desde reinterpretaciones char se permite explícitamente (como he dicho anteriormente), no hay ninguna advertencia aquí. Por otra parte, conversiones explícitas por lo general tienden a suprimir cualquier advertencia, ya que son una forma de decirle al compilador que usted realmente quiere hacer algo, independientemente de lo equivocado y / o peligrosa que podría ser.

Otros consejos

un elenco de cualquier tipo de puntero a char * está explícitamente permitido por el lenguaje C. por lo que la mayor parte de esto está muy bien.

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

La primera parte está bien x = (char*)&b[0]; establece un puntero char al comienzo de la matriz. La prueba es también bien x <= (char *)&b[9][9] será verdad siempre que x puntos dentro de la matriz.

x += sizeof(a+1) es la parte dudoso. En la mayoría de sizeof arquitecturas de CPU de 32 bits (int *) acaba de sucede a ser el mismo que sizeof (int), por lo que este código es probable que trabajo , pero sólo por accidente.

Estoy seguro de que lo que se pretendía era x += sizeof(a[0]) o x += sizeof(b[0]), pero ya que el código realmente hizo lo que se pretendía, nadie di cuenta del error.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top