Tenemos la mejor información que hemos encontrado on line. Nosotros deseamos que te sea de ayuda y si puedes compartir algún detalle que nos pueda ayudar a mejorar hazlo libremente.
Solución:
El punto del autor es que declarar una variable con register
la clase de almacenamiento le impide tomar su dirección, por lo que no se puede pasar a una función que podría cambiar su valor al desecharla const
.
void bad_func(const int *p)
int *q = (int *) p; // casting away const
*q = 42; // potential undefined behaviour
void my_func()
int i = 4;
const int j = 5;
register const int k = 6;
bad_func(&i); // ugly but allowed
bad_func(&j); // oops - undefined behaviour invoked
bad_func(&k); // constraint violation; diagnostic required
Al cambiar el UB potencial a una violación de restricción, se requiere un diagnóstico y el error es (es necesario que sea) diagnosticado en tiempo de compilación:
c11
5.1.1.3 Diagnóstico
1 – Una implementación conforme deberá producir al menos un mensaje de diagnóstico […] si una unidad de traducción de preprocesamiento o unidad de traducción contiene una violación de cualquier regla o restricción de sintaxis, incluso si el comportamiento también se especifica explícitamente como indefinido o definido por la implementación.
6.5.3.2 Operadores de dirección e indirección
Restricciones
1 – El operando del unario
&
el operador será […] un lvalue que designa un objeto que […] no se declara con elregister
especificador de clase de almacenamiento.
Tenga en cuenta que arraydecaimiento de -a-puntero en un register
array objeto es un comportamiento indefinido que no requiere ser diagnosticado (6.3.2.1:3).
Tenga en cuenta también que tomar la dirección de un register
valor es permitido en C++, donde register
es solo una sugerencia de optimización (y una obsoleta).
¿Podemos modificar el valor de un
const
¿variable?
Sí, puede modificar un const
variable a través de varios medios: Pointer hackery, casts etc…
¡Lea la próxima Q!
¿Es un código válido para modificar el valor de un
const
¿variable?
¡No! Lo que eso te da es Comportamiento indefinido.
Técnicamente, su ejemplo de código tiene un Comportamiento indefinido.
El programa no se adhiere al estándar c una vez que modifica el const
y por lo tanto puede dar cualquier resultado.
Tenga en cuenta que un Comportamiento indefinido no significa que el compilador deba informar la infracción como un diagnóstico. En este caso, su código usa piratería de punteros para modificar un const
y el compilador no es necesario para proporcionarle un diagnóstico.
El C99 estándar 3.4.3 dice:
Comportamiento indefinido: comportamiento, ante el uso de una construcción de programa errónea o no portátil o de datos erróneos, para los cuales esta Norma Internacional no impone requisitos.
NOTA El posible comportamiento indefinido varía desde ignorar la situación por completo con resultados impredecibles, comportarse durante la traducción o ejecución del programa de una manera documentada característica del entorno (con o sin la emisión de un mensaje de diagnóstico), hasta terminar una traducción o ejecución (con la emisión de un mensaje de diagnóstico).
Su código se compila, pero tiene un comportamiento indefinido.
El punto del autor es usar const
yregister
para que el código ya no compile:
const int a = 81;
int *p = (int *)&a; /* no compile error */
*p = 42; /* UB */
register const int b = 81;
int *q = (int *)&b; /* does not compile */
Reseñas y calificaciones
Eres capaz de añadir valor a nuestra información asistiendo con tu veteranía en las ilustraciones.