conversão de bool para int

131

Quão portátil é essa conversão. Posso ter certeza de que ambas as afirmações são aprovadas?

int x = 4<5;
assert(x==1);

x = 4>5;
assert(x==0);

Não pergunte o porquê. Eu sei que é feio. Obrigado.

pic11
fonte
Por que você não muda a primeira expressão? Você pode escrever assert(x!=0). Mesmo que bool (true) converta portável em int (1), o "not false" afirma tem uma expressão mais legível.
harper
1
Por que não: assert( 4 < 5);eassert(!( 4 > 5));
Martin York
4
@ harper: Usar o valor necessário de uma expressão de comparação é perfeitamente razoável.
R .. GitHub Pare de ajudar o gelo
@ R._ Quando a questão é se a conversão bool-para-int fornece um resultado razoável, eu não confiaria nisso. Quando o autor tem dúvidas de que esse requisito foi atendido, o leitor pode obter o mesmo problema. Especialmente porque o valor de x não é a condição para verificar, mas apenas um resultado intermediário.
Harper
3
Eu provavelmente escreveria (4 < 5) ? 1 : 0se realmente precisar converter um booleano em 0 ou 1. Um bom compilador provavelmente produzirá o mesmo código de máquina e é mais claro para um leitor humano.
ollb

Respostas:

205
int x = 4<5;

Completamente portátil. Conformista padrão. boola intconversão está implícita!

§4.7 / 4 do padrão C ++ diz ( Conversão integral )

Se o tipo de fonte for booleano, o valor falseserá convertido em zero e o valor trueserá convertido em um .


Quanto a C, até onde eu sei, não existe boolem C. (antes de 1999). Portanto, boola intconversão é relevante apenas em C ++. Em C, 4<5avalia como intvalor, neste caso, o valor é 1, 4>5 avaliaria como 0.

Edição: Jens no comentário disse, C99 tem _Booltipo. boolé uma macro definida no stdbool.harquivo de cabeçalho. truee falsetambém são macro definidos em stdbool.h.

§7.16 do C99 diz:

A macro se boolexpande para _Bool.

[..] trueque se expande para a constante inteira 1, false que se expande para a constante inteira 0, [..]

Nawaz
fonte
3
verifique se existe boolem C desde 1999. Basta usar o cabeçalho "stdbool.h" e isso deve ser incluído.
Jens Gustedt
1
Na verdade, eu verifiquei em vários compiladores e parece ser portátil.
pic11
8
Independentemente da versão da linguagem C e da disponibilidade de bool/ _Booltype, os operadores relacionais em C produzem int, não bool. Ou seja, mesmo em C99, os operadores relacionais ainda produzem int.
AnT
51

Você marcou sua pergunta [C] e [C ++] ao mesmo tempo. Os resultados serão consistentes entre os idiomas, mas a estrutura da resposta é diferente para cada um desses idiomas.

Na linguagem C, seus exemplos não têm relação boolalguma (isso também se aplica a C99). Na linguagem C, os operadores relacionais não produzem boolresultados. Ambas 4 > 5e 4 < 5são expressões que produzem resultados do tipo intcom valores 0ou1 . Portanto, não há nenhum tipo de "conversão de bool para int" ocorrendo nos seus exemplos em C.

No C ++, os operadores relacionais realmente produzem boolresultados. boolos valores são conversíveis em inttipo, com trueconversão para 1e falseconversão para0 . Isso é garantido pelo idioma.

A linguagem PS C também possui um tipo booleano dedicado _Bool(com alias de macro como bool) e suas regras de conversão integrais são essencialmente as mesmas que em C ++. Mas, no entanto, isso não é relevante para seus exemplos específicos em C. Mais uma vez, os operadores relacionais em C sempre produzem int(não bool) resultados, independentemente da versão da especificação da linguagem.

Formiga
fonte
2
Isso mesmo, não há bool na K&R C. Marquei novamente minha pergunta como C99.
pic11
@ pic11: Não havia necessidade de marcar novamente nada. Não tem nada a ver com K&R ou qualquer outro C. Mesmo que haja boolno C99, os operadores relacionais ainda produzem intno C99, não bool. Portanto, se você está interessado em operadores relacionais específicos (como nos exemplos), o problema ainda não tem nada a ver bool.
AnT
Agora eu entendi. O resultado do operador de relação implicitamente conversível em int. Isso é verdade em C, C99 e C ++. Tarou novamente.
pic11
3
@ pic11: Não, você não entendeu. Em C, incluindo C99, o resultado de um operador de comparação é um int, não um bool. Nenhuma conversão acontece.
R .. GitHub Pare de ajudar o gelo
Existe alguma maneira de conformidade com os padrões através da qual um idioma possa ter um tipo que se comporte como, boolmas não permita que seu endereço seja utilizado? Muitos sistemas embarcados fazem uso desses tipos (geralmente declarados usando o identificador bit). Em, por exemplo, um PIC de gama média, if (bitVar1) bitVar2=1;haveria duas instruções; a codificação ideal para if (byteVar1) byteVar2=1;pelo menos quatro (em muitos compiladores, provavelmente cinco). Esses tipos podem, portanto, oferecer um grande aumento de desempenho.
Supercat
17

A seção 6.5.8.6 da norma C diz:

Cada um dos operadores <(menor que),> (maior que), <= (menor ou igual a) e> = (maior que ou igual a) deve produzir 1 se a relação especificada for verdadeira e 0 se for false.) O resultado tem o tipo int.


fonte
Obrigado pela referência. Parece verdadeiro == 1 por razões históricas.
pic11
2

Parece não haver nenhum problema, já que a conversão de int para bool é feita implicitamente. Isso funciona no Microsoft Visual C ++, GCC e compilador Intel C ++. Não há problema em C ou C ++.

Alex James
fonte
2
"Funciona em alguns casos" não é uma boa maneira de verificar a correção, especialmente em versões não especificadas dessas ferramentas. Eu prefiro a abordagem nas outras respostas; eles não podem garantir que uma implementação específica esteja correta, mas podem garantir o que uma implementação correta fará.
Matthew Leia