Eu tenho um pequeno pedaço de código sobre o sizeof
operador com o operador ternário:
#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;
}
Saída ( GCC ):
1
1
4 // Why 4?
Mas aqui,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
o operador ternário retorna boolean
tipo e tamanho do bool
tipo é 1
byte em C.
Então, por que sizeof(a ? true : false)
fornecer uma saída de quatro bytes?
sizeof(true)
esizeof(false)
também é 4: ide.geeksforgeeks.org/O5jvuN_Bool
tamanho 1, mas nãotrue
efalse
. Mas o padrão não tem nada a dizer sobre isso, tanto quanto eu posso dizer.char a;
sizeof(a) == 1
esizeof('a') == sizeof(int)
(em C). Não é sobre a implementação, é sobre a linguagem.sizeof(true)
? talvez isso torne as coisas um pouco mais claras (em particular, ficará óbvio que o operador ternário é um arenque vermelho).true
é#define
d 1stdbool.h
como sim, esta é a definição literal.Respostas:
É porque você tem
#include <stdbool.h>
. Esse cabeçalho define macrostrue
efalse
be ,1
e0
, portanto, sua declaração é assim:sizeof(int)
é 4 na sua plataforma.fonte
sizeof(a ? (uint8_t)1 : (uint8_t)0);
também daria um resultado de 4. A promoção inteira dos?:
operandos é a parte importante aqui, não o tamanho detrue
efalse
.int
sem promoção. O motivo pelo qual você não pode "consertar" são as promoções padrão.true
e nãofalse
são macros; são palavras-chave. Eles não estão definidos para ser e , mas para ser os valores verdadeiros e falsos do tipo.1
0
bool
sizeof(true)
é 1. demo .OK, há mais do que isso!
Em C, o resultado dessa operação ternária é do tipo
int
. [notas abaixo (1,2)]Portanto, o resultado é o mesmo que a expressão
sizeof(int)
na sua plataforma.Nota 1: Citação
C11
, capítulo §7.18,Boolean type and values <stdbool.h>
Nota 2: Para operador condicional, capítulo §6.5.15, ( ênfase minha )
e
portanto, o resultado será do tipo inteiro e, devido ao intervalo de valores, as constantes são precisamente do tipo
int
.Dito isto, um conselho genérico
int main()
deve ser melhorint main (void)
para ser verdadeiramente compatível com os padrões.fonte
<stdbool.h>
define o MACROS para ser do tipoint
..é errado?O operador ternário é um arenque vermelho.
imprime 4 (ou o que
sizeof(int)
estiver na sua plataforma).O seguinte pressupõe que
bool
é um sinônimochar
ou um tipo semelhante de tamanho 1 eint
é maior quechar
.A razão pela qual
sizeof(true) != sizeof(bool)
esizeof(true) == sizeof(int)
é simplesmente porque nãotrue
é uma expressão do tipo . É uma expressão do tipo . É d como em .bool
int
#define
1
stdbool.h
Não há valores de tipoEditar: este parágrafo não é verdadeiro, argumentos parabool
em C. Todo esse valor é imediatamente promovido paraint
, mesmo quando usado como argumento parasizeof
.sizeof
os quais não é promovidoint
. Isso não afeta nenhuma das conclusões.fonte
(bool)1
um rvalor do tipobool
?printf("%u\n", sizeof((char) 1));
imprime1
na minha plataforma enquantoprintf("%u\n", sizeof(1));
imprime4
. Isso não significa que sua declaração "Todo valor desse valor é imediatamente promovido para int, mesmo quando usado como argumento para sizeof" é falsa?true
etc realmente não importa no caso de,?:
uma vez que é promovido inteiro paraint
qualquer forma. Ou seja, a resposta deve abordar o porquê de?:
um arenque vermelho.Em relação ao tipo booleano em C
Um tipo booleano foi introduzido bastante tarde na linguagem C, no ano de 1999. Antes disso, C não tinha um tipo booleano, mas era usado
int
para todas as expressões booleanas. Portanto, todos os operadores lógicos, como> == !
etc, retornam umint
valor1
ou0
.Era costume que os aplicativos usassem tipos caseiros como
typedef enum { FALSE, TRUE } BOOL;
, que também se resume aint
tipos de tamanho.O C ++ tinha um tipo booleano muito melhor e explícito
bool
, que não era maior que 1 byte. Enquanto os tipos ou expressões booleanos em C terminariam em 4 bytes no pior caso. Alguma maneira de compatibilidade com C ++ foi introduzida em C com o padrão C99. C então obteve um tipo booleano_Bool
e também o cabeçalhostdbool.h
.stdbool.h
fornece alguma compatibilidade com C ++. Esse cabeçalho define a macrobool
(a mesma ortografia que a palavra-chave C ++) que se expande para_Bool
, um tipo que é um tipo inteiro pequeno, provavelmente com 1 byte de largura. Da mesma forma, o cabeçalho fornece dois macrostrue
efalse
, mesmo ortografia como palavras-chave C ++, mas com compatibilidade com versões anteriores para programas em C mais velhos . Por issotrue
efalse
expandir-se para1
e0
em C e seu tipo éint
. Essas macros não são realmente do tipo booleano, como seriam as palavras-chave C ++ correspondentes.Da mesma forma, para fins de compatibilidade com versões anteriores, os operadores lógicos em C ainda retornam um
int
até hoje, mesmo que C atualmente tenha um tipo booleano. Enquanto em C ++, operadores lógicos retornam abool
. Assim, uma expressão comosizeof(a == b)
dará o tamanho de umint
em C, mas o tamanho de umbool
em C ++.Em relação ao operador condicional
?:
O operador condicional
?:
é um operador estranho com algumas peculiaridades. É um erro comum acreditar que é 100% equivalente aif() { } else {}
. Não é bem assim.Há um ponto de sequência entre a avaliação do 1º e do 2º ou 3º operando. O
?:
operador é garantido apenas para avaliar tanto o 2º ou o 3º operando, por isso não pode executar quaisquer efeitos colaterais do operando que não é avaliado. Código comotrue? func1() : func2()
não será executadofunc2()
. Por enquanto, tudo bem.No entanto , existe uma regra especial que afirma que o segundo e o terceiro operando devem ser implicitamente promovidos e equilibrados entre si com as conversões aritméticas usuais . ( Regras implícitas de promoção de tipo em C explicadas aqui ). Isso significa que o segundo ou terceiro operando sempre será pelo menos tão grande quanto um
int
.Portanto, não importa isso
true
efalse
seja do tipoint
C, porque a expressão sempre daria pelo menos o tamanho de umint
não.Mesmo se você reescrevesse a expressão, ela retornaria o tamanho de um !
sizeof(a ? (bool)true : (bool)false)
int
Isso ocorre devido à promoção implícita de tipo por meio das conversões aritméticas usuais.
fonte
sizeof(bool)==1
.Resposta rápida:
sizeof(a ? true : false)
é avaliado como4
porquetrue
efalse
é definido<stdbool.h>
como1
e0
respectivamente, para que a expressão se expanda parasizeof(a ? 1 : 0)
uma expressão inteira com o tipoint
, que ocupa 4 bytes na sua plataforma. Pelo mesmo motivo, vocêsizeof(true)
também avaliaria4
em seu sistema.Observe no entanto que:
sizeof(a ? a : a)
também avalia4
porque o operador ternário executa as promoções de números inteiros em seu segundo e terceiro operandos, se forem expressões de número inteiro. O mesmo, naturalmente, acontece porsizeof(a ? true : false)
esizeof(a ? (bool)true : (bool)false)
, mas lançando a expressão inteira comobool
se comporta como esperado:sizeof((bool)(a ? true : false)) -> 1
.Também note que os operadores de comparação avaliar a valores booleanos
1
ou0
, mas temint
tipo:sizeof(a == a) -> 4
.Os únicos operadores que mantêm a natureza booleana
a
seriam:o operador de vírgula: ambos
sizeof(a, a)
esizeof(true, a)
avaliar1
em tempo de compilação.os operadores de atribuição: ambos
sizeof(a = a)
esizeof(a = true)
têm um valor de1
.os operadores de incremento:
sizeof(a++) -> 1
Finalmente, todas as opções acima se aplicam apenas a C: C ++ possui semânticas diferentes em relação ao
bool
tipo, valores booleanostrue
efalse
operadores de comparação e operador ternário: todas essassizeof()
expressões são avaliadas1
em C ++.fonte
true
e quefalse
são, porque os?:
operandos seriam promovidos a números inteiros deint
qualquer maneira. Assimsizeof(a ? (uint8_t)true : (uint8_t)false)
, também produzirá 4 como resultado.int
Aqui está um trecho do qual é incluído na fonte
Existem macros
true
efalse
são declaradas como 1 e 0, respectivamente.no entanto, nesse caso, o tipo é o tipo das constantes literais. 0 e 1 são constantes inteiras que se encaixam em um int, portanto, seu tipo é int.
e
sizeof(int)
no seu caso é 4.fonte
Não há tipo de dados booleano em C; expressões lógicas são avaliadas para valores inteiros
1
quando true, caso contrário0
.Expressões condicionais como
if
,for
,while
, ouc ? a : b
esperar um inteiro, se o número for diferente de zero é consideradotrue
com exceção de alguns casos especiais, aqui está uma função de soma recursivo em que o ternário-operador irá avaliartrue
até quen
alcance0
.Também pode ser usado para
NULL
verificar um ponteiro, aqui está uma função recursiva que imprime o conteúdo de uma lista vinculada vinculada.fonte