2010-09-21 7 views
6

tengo una función que toma un entero largo sin signo * y tiene que pasar a una biblioteca externa que toma un unsigned int * y en esta plataforma unsigned int/larga son del mismo tamaño.Un molde que está rompiendo las reglas estrictas-aliasing

void UpdateVar(unsigned long* var) { 
    // this function will change the value at the address of var 
    ExternalLibAtomicUpdateVar((unsigned int*)var); // lib atomically updates variable 
} 

Esto genera una advertencia diciendo que su romper las reglas estrictas-aliasing. ¿Hay algún problema?

Gracias

Editar: Me disculpo por no ser clara. El código es una actualización atómica, por lo que ir por la biblioteca para almacenarlo no es una opción. Podría bajar a ensamblar, pero me gustaría hacer esto en C++.

+0

sólo para un único objeto o una matriz de enteros largos /? – sellibitze

+0

Es una tienda atómica con una única pieza de memoria de 32 bits. – coderdave

Respuesta

8
void UpdateVar(unsigned long* var) { 
    unsigned int x = static_cast<unsigned int>(*var); 
    ExternalLibUpdateVar(&x); 
    *var = static_cast<unsigned long>(x); 
} 
+0

Haz ese 'static_cast's, y yo votaré. – sbi

+0

Lo siento; no notó la etiqueta C++ – dave

+0

¿Cuál es la diferencia real entre 'static_cast' y' reinterpret_cast' en este caso? – identity

2

Esto debería funcionar:

void UpdateVar(unsigned long* var) { 
    // this function will change the value at the address of var 
    ExternalLibUpdateVar(reinterpret_cast<unsigned int*>(var)); 
} 
+0

peligroso si sizeof (largo)! = Sizeof (int) – nos

+0

Dijo que en el post original que se garantiza que sea del mismo tamaño en su plataforma. Pero sí, tienes razón. – identity

+1

+1. Bajo ciertas condiciones, esto es realmente apropiado en mi opinión. Pero realmente depende de cada caso y me siento más cómodo con algún tipo de 'sizeof (int) == sizeof (long)' comprobar en el programa que hace la compilación falle en caso de que no se cumple la condición - C++ 0x's 'static_cast' alguien? :-) – sellibitze

0

Nada en los mandatos C estándar que int y long deben tener el mismo tamaño; Además, incluso si lo hacen tienen el mismo tamaño, nada en los mandatos estándar que tienen la misma representación (entre otras cosas, que podrían tener las combinaciones incompatibles de bits de relleno y representaciones trampa, de tal manera que aliasing entre los dos tipos no podía servir a cualquier propósito útil).

Los autores de la Norma no deseaban forzar a los implementadores a plataformas donde el alias entre int y long no serviría para reconocer dicho alias. Tampoco quisieron escribir reglas que serían aplicables a algunas plataformas (aquellas en las que el alias serviría para un propósito) pero no a otras (aquellas en las que no sería así). En su lugar, pensaron que las personas que escriben compiladores de calidad tratarían de reconocer el alias en los casos en los que era útil.

Ser capaz de utilizar punteros a un tipo de 32 bits a leer y escribir valores de otro tipo de 32 bits que tiene la misma representación es claramente útil, sobre todo si las API están divididos en cuanto a qué tipo de lo que esperan. Si algunas API comunes en una plataforma usan int* para valores de 32 bits y otras usan long*, una calidad implementación de propósito general para esa plataforma debe permitir el acceso a datos de cualquier tipo utilizando punteros de la otra. No obstante, los autores de algunos compiladores están más interesados ​​en procesar un cierto subconjunto de programas rápidamente que en procesar un subconjunto más grande de programas de manera útil, y no se puede confiar en que generen código útil si es necesario intercambiar datos. entre API que utilizan la misma representación de datos pero diferentes tipos con nombre, a menos que se deshabilite completamente el análisis de aliasing. Por supuesto, si uno se dirige a dialectos de C que son adecuados para uso general en microcontroladores, dichos problemas no importan.

Cuestiones relacionadas