Tengo un pequeño fragmento de código sobre el sizeofoperador 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 booleantipo y el tamaño del booltipo es 1byte 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_Booltener el tamaño 1, pero notrueyfalse. Pero el estándar no tiene nada que decir al respecto por lo que puedo decir.char a;sizeof(a) == 1ysizeof('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).truees#defined ser 1 porstdbool.hlo que sí, esta es la definición literal.Respuestas:
Es porque tienes
#include <stdbool.h>. Ese encabezado define macrostrueyfalseser1y0, 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 detrueyfalse.intno tiene promoción. La razón por la que no puede "arreglarlo" son las promociones predeterminadas.truey nofalseson macros; Son palabras clave. No están definidos para ser y , sino para ser los valores verdaderos y falsos del tipo.10boolsizeof(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
booles un sinónimocharo un tipo similar de tamaño 1, yintes mayor quechar.La razón por la cual
sizeof(true) != sizeof(bool)ysizeof(true) == sizeof(int)es simplemente porque notruees una expresión de tipo . Es una expresión de tipo . Es d como en .boolint#define1stdbool.hNo hay valores de tipoEditar: este párrafo no es cierto, argumentos paraboolen C en absoluto. Todos estos valores se promueven de inmediatoint, incluso cuando se usan como argumento parasizeof.sizeofno ser promovidoint. Sin embargo, esto no afecta a ninguna de las conclusiones.fuente
(bool)1un valor de tipobool?printf("%u\n", sizeof((char) 1));imprime1en 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?trueetc. realmente no importan en el caso de?:que, deinttodos 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
intpara todas las expresiones booleanas. Por lo tanto, todos los operadores lógicos como> == !etc. devuelven unintvalor1o0.Fue personalizado para las aplicaciones utilizar tipos caseros como
typedef enum { FALSE, TRUE } BOOL;, que también se reduce ainttipos 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_Booly también el encabezadostdbool.h.stdbool.hProporciona 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 macrostrueyfalse, misma ortografía como palabras clave C ++, pero con compatibilidad con versiones anteriores de los programas en C de más edad . Por lo tantotrueyfalseampliar a1y0en 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
inthasta 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 aninten C, pero el tamaño de aboolen 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
trueyfalseresulta ser de tipointC porque la expresión siempre daría al menos el tamaño de unintno importa.¡Incluso si reescribiera la expresión , aún devolvería el tamaño de un !
sizeof(a ? (bool)true : (bool)false)intEsto 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 como4porquetrueyfalsese definen<stdbool.h>como1y0respectivamente, 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ía4en su sistema.Sin embargo, tenga en cuenta que:
sizeof(a ? a : a)también evalúa4porque 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 comoboolse comporta como se esperaba:sizeof((bool)(a ? true : false)) -> 1.También señalan que los operadores de comparación albergar valores booleanos
1o0, mas tengaintTipo:sizeof(a == a) -> 4.Los únicos operadores que mantienen la naturaleza booleana de
aserían:el operador de coma: ambos
sizeof(a, a)ysizeof(true, a)evaluar1en 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++) -> 1Finalmente, todo lo anterior se aplica solo a C: C ++ tiene una semántica diferente con respecto al
booltipo, los valores booleanostruey losfalseoperadores de comparación y el operador ternario: todas estassizeof()expresiones se evalúan1en C ++.fuente
truey quéfalseson, porque los?:operandos serían promovidos a enteros deinttodos modos. Porsizeof(a ? (uint8_t)true : (uint8_t)false)lo tanto , también dará 4 como resultado.intAquí hay un fragmento del cual es lo que se incluye en la fuente
Hay macros
trueyfalsese 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
1cuando es verdadero de lo contrario0.Las expresiones condicionales como
if,for,while, oc ? a : besperar un entero, si el número no es cero se consideratruea excepción de algunos casos especiales, he aquí una función suma recursiva en la que el operador ternario-evaluarátruehasta quenalcance0.También se puede usar para
NULLverificar un puntero, aquí hay una función recursiva que imprime el contenido de una Lista enlazada individualmente.fuente