Tengo un pequeño fragmento de código sobre el sizeof
operador con el operador ternario:
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool a = true;
printf("%zu\n", sizeof(bool)); // Ok
printf("%zu\n", sizeof(a)); // Ok
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
return 0;
}
Salida ( GCC ):
1
1
4 // Why 4?
Pero aquí,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
el operador ternario devuelve el boolean
tipo y el tamaño del bool
tipo es 1
byte en C.
Entonces, ¿por qué sizeof(a ? true : false)
da una salida de cuatro bytes?
sizeof(true)
ysizeof(false)
también es 4: ide.geeksforgeeks.org/O5jvuN_Bool
tener el tamaño 1, pero notrue
yfalse
. Pero el estándar no tiene nada que decir al respecto por lo que puedo decir.char a;
sizeof(a) == 1
ysizeof('a') == sizeof(int)
(en C). No se trata de la implementación, se trata del lenguaje.sizeof(true)
? tal vez aclarará un poco más las cosas (en particular, será obvio que el operador ternario es un arenque rojo).true
es#define
d ser 1 porstdbool.h
lo que sí, esta es la definición literal.Respuestas:
Es porque tienes
#include <stdbool.h>
. Ese encabezado define macrostrue
yfalse
ser1
y0
, por lo que su declaración se ve así:sizeof(int)
es 4 en tu plataforma.fuente
sizeof(a ? (uint8_t)1 : (uint8_t)0);
también daría un resultado de 4. La promoción entera de los?:
operandos es la parte importante aquí, no el tamaño detrue
yfalse
.int
no tiene promoción. La razón por la que no puede "arreglarlo" son las promociones predeterminadas.true
y nofalse
son macros; Son palabras clave. No están definidos para ser y , sino para ser los valores verdaderos y falsos del tipo.1
0
bool
sizeof(true)
es 1. demo .OK, hay más que eso!
En C, el resultado de esta operación ternaria es de tipo
int
. [notas a continuación (1,2)]Por lo tanto, el resultado es el mismo que la expresión
sizeof(int)
, en su plataforma.Nota 1: Cita
C11
, capítulo §7.18,Boolean type and values <stdbool.h>
Nota 2: Para operador condicional, capítulo §6.5.15, ( énfasis mío )
y
por lo tanto, el resultado será de tipo entero y, debido al rango de valores, las constantes son precisamente de tipo
int
.Dicho esto, un consejo genérico,
int main()
debería ser mejor cumplirint main (void)
con los estándares.fuente
<stdbool.h>
define que los MACROS son de tipoint
... ¿está mal?El operador ternario es un arenque rojo.
imprime 4 (o lo
sizeof(int)
que sea que esté en su plataforma).Lo siguiente supone que
bool
es un sinónimochar
o un tipo similar de tamaño 1, yint
es mayor quechar
.La razón por la cual
sizeof(true) != sizeof(bool)
ysizeof(true) == sizeof(int)
es simplemente porque notrue
es una expresión de tipo . Es una expresión de tipo . Es d como en .bool
int
#define
1
stdbool.h
No hay valores de tipoEditar: este párrafo no es cierto, argumentos parabool
en C en absoluto. Todos estos valores se promueven de inmediatoint
, incluso cuando se usan como argumento parasizeof
.sizeof
no ser promovidoint
. Sin embargo, esto no afecta a ninguna de las conclusiones.fuente
(bool)1
un valor de tipobool
?printf("%u\n", sizeof((char) 1));
imprime1
en mi plataforma mientrasprintf("%u\n", sizeof(1));
imprime4
. ¿No significa esto que su afirmación "Cada uno de esos valores se promueve inmediatamente a int, incluso cuando se usa como argumento para sizeof" es falsa?true
etc. realmente no importan en el caso de?:
que, deint
todos modos, se promueve un número entero . Es decir, la respuesta debe abordar por qué?:
es un arenque rojo.En cuanto al tipo booleano en C
Un tipo booleano se introdujo bastante tarde en el lenguaje C, en el año 1999. Antes de eso, C no tenía un tipo booleano, sino que se usaba
int
para todas las expresiones booleanas. Por lo tanto, todos los operadores lógicos como> == !
etc. devuelven unint
valor1
o0
.Fue personalizado para las aplicaciones utilizar tipos caseros como
typedef enum { FALSE, TRUE } BOOL;
, que también se reduce aint
tipos de tamaño.C ++ tenía un tipo booleano mucho mejor y explícito
bool
, que no era mayor de 1 byte. Mientras que los tipos booleanos o expresiones en C terminarían como 4 bytes en el peor de los casos. Se introdujo algún tipo de compatibilidad con C ++ en C con el estándar C99. C luego obtuvo un tipo booleano_Bool
y también el encabezadostdbool.h
.stdbool.h
Proporciona cierta compatibilidad con C ++. Este encabezado define la macrobool
(la misma ortografía que la palabra clave C ++) que se expande a_Bool
, un tipo que es un tipo entero pequeño, probablemente 1 byte grande. Del mismo modo, la cabecera proporciona dos macrostrue
yfalse
, misma ortografía como palabras clave C ++, pero con compatibilidad con versiones anteriores de los programas en C de más edad . Por lo tantotrue
yfalse
ampliar a1
y0
en C y su tipo esint
. Estas macros no son en realidad del tipo booleano como lo serían las palabras clave correspondientes de C ++.Del mismo modo, para fines de compatibilidad con versiones anteriores, los operadores lógicos en C aún devuelven un
int
hasta el día de hoy, a pesar de que C actualmente tiene un tipo booleano. Mientras que en C ++, los operadores lógicos devuelven abool
. Por lo tanto, una expresión tal comosizeof(a == b)
dará el tamaño de anint
en C, pero el tamaño de abool
en C ++.Sobre el operador condicional
?:
El operador condicional
?:
es un operador extraño con un par de peculiaridades. Es un error común creer que es 100% equivalente aif() { } else {}
. No exactamente.Hay un punto de secuencia entre la evaluación del primer y segundo o tercer operando. Se
?:
garantiza que el operador solo evaluará el segundo o el tercer operando, por lo que no puede ejecutar ningún efecto secundario del operando que no se evalúe. Código comotrue? func1() : func2()
no se ejecutaráfunc2()
. Hasta aquí todo bien.Sin embargo , hay una regla especial que establece que los operandos segundo y tercero deben obtener implícitamente el tipo promocionado y equilibrado entre sí con las conversiones aritméticas habituales . ( Las reglas de promoción de tipo implícito en C se explican aquí ). Esto significa que el segundo o tercer operando siempre será al menos tan grande como un
int
.Por lo tanto, no importa eso
true
yfalse
resulta ser de tipoint
C porque la expresión siempre daría al menos el tamaño de unint
no importa.¡Incluso si reescribiera la expresión , aún devolvería el tamaño de un !
sizeof(a ? (bool)true : (bool)false)
int
Esto se debe a la promoción de tipo implícito a través de las conversiones aritméticas habituales.
fuente
sizeof(bool)==1
.Respuesta rápida:
sizeof(a ? true : false)
se evalúa como4
porquetrue
yfalse
se definen<stdbool.h>
como1
y0
respectivamente, por lo que la expresión se expande asizeof(a ? 1 : 0)
una expresión entera con tipoint
, que ocupa 4 bytes en su plataforma. Por la misma razón,sizeof(true)
también evaluaría4
en su sistema.Sin embargo, tenga en cuenta que:
sizeof(a ? a : a)
también evalúa4
porque el operador ternario realiza las promociones enteras en su segundo y tercer operandos si son expresiones enteras. Lo mismo sucede, por supuesto, parasizeof(a ? true : false)
ysizeof(a ? (bool)true : (bool)false)
, pero echando toda la expresión comobool
se comporta como se esperaba:sizeof((bool)(a ? true : false)) -> 1
.También señalan que los operadores de comparación albergar valores booleanos
1
o0
, mas tengaint
Tipo:sizeof(a == a) -> 4
.Los únicos operadores que mantienen la naturaleza booleana de
a
serían:el operador de coma: ambos
sizeof(a, a)
ysizeof(true, a)
evaluar1
en tiempo de compilación.los operadores de asignación: ambos
sizeof(a = a)
ysizeof(a = true)
tienen un valor de1
.los operadores de incremento:
sizeof(a++) -> 1
Finalmente, todo lo anterior se aplica solo a C: C ++ tiene una semántica diferente con respecto al
bool
tipo, los valores booleanostrue
y losfalse
operadores de comparación y el operador ternario: todas estassizeof()
expresiones se evalúan1
en C ++.fuente
true
y quéfalse
son, porque los?:
operandos serían promovidos a enteros deint
todos modos. Porsizeof(a ? (uint8_t)true : (uint8_t)false)
lo tanto , también dará 4 como resultado.int
Aquí hay un fragmento del cual es lo que se incluye en la fuente
Hay macros
true
yfalse
se declaran como 1 y 0 respectivamente.sin embargo, en este caso, el tipo es el tipo de las constantes literales. Tanto 0 como 1 son constantes enteras que caben en un int, por lo que su tipo es int.
y el
sizeof(int)
en tu caso es 4.fuente
No hay ningún tipo de datos booleanos en C, en su lugar, las expresiones lógicas se evalúan a valores enteros
1
cuando es verdadero de lo contrario0
.Las expresiones condicionales como
if
,for
,while
, oc ? a : b
esperar un entero, si el número no es cero se consideratrue
a excepción de algunos casos especiales, he aquí una función suma recursiva en la que el operador ternario-evaluarátrue
hasta quen
alcance0
.También se puede usar para
NULL
verificar un puntero, aquí hay una función recursiva que imprime el contenido de una Lista enlazada individualmente.fuente