Estaba tratando de escribir algunas macros para el uso seguro de tipos de _Bool
y luego prueba de estrés mi código. Para propósitos de pruebas diabólicas, se me ocurrió este sucio truco:
_Bool b=0;
*(unsigned char*)&b = 42;
Dado que _Bool
es 1 byte en la implementación sizeof(_Bool)==1
), no veo cómo este truco viola el estándar C. No debería ser una violación estricta de aliasing.
Sin embargo, cuando ejecuto este programa a través de varios compiladores, tengo problemas:
#include <stdio.h>
int main(void)
{
_Static_assert(sizeof(_Bool)==1, "_Bool is not 1 byte");
_Bool b=0;
*(unsigned char*)&b = 42;
printf("%d ", b);
printf("%d", b!=0 );
return 0;
}
(El código se basa en printf
promoción implícita de argumento predeterminado a int
)
Algunas versiones de gcc y clang dan salida 42 42
otros dan 0 0
. Incluso con las optimizaciones deshabilitadas. hubiera esperado 42 1
.
Parecería que los compiladores asumen que _Bool
Solo puede ser 1
o 0
pero al mismo tiempo felizmente imprime 42
en el primer caso.
P1: ¿Por qué es esto? ¿El código anterior contiene un comportamiento indefinido?
P2: ¿Qué tan confiable es sizeof(_Bool)
? C17 6.5.3.4 no menciona _Bool
en absoluto.
como puede ser la salida
42 42
? El segundo printf solo puede imprimir 1 o 0.– StoryTeller – Unslander Mónica
4 sep 2018 a las 10:53
O_O lo probé. Mi mente está seriamente volada en este momento. Esto se une a mi colección de ejemplos de UB.
– StoryTeller – Unslander Mónica
4 sep 2018 a las 10:58
No sé. Aunque inicialmente me sorprendió el segundo 42, tiene sentido en retrospectiva. Porque
b != 0
para_Bool
se puede optimizar para simplementeb
. Aunque todavía me estoy rascando la cabeza.– StoryTeller – Unslander Mónica
4 sep 2018 a las 11:02
@RbMm Los tipos de caracteres son una excepción en las estrictas reglas de alias. Optimizer no puede causar UB basado en eso aquí.
– usuario694733
4 sep 2018 a las 11:04
En un ejemplo similar, el
_Bool
La optimización se combina con optimizaciones para transformar ramas en operaciones aritméticas, produciendo resultados de aspecto extraño para un código muy natural. La optimización deif (b) x++;
enx+=(the representation of )b;
confirma que Clang trata_Bool
representaciones que no sean0
y1
como valores trampa que activan UB. gcc.godbolt.org/z/wPq4zq– Pascal Cuoq
04/09/2018 a las 11:25