Sabemos que quaisquer números que não sejam iguais a 0
são vistos como true
em C, então podemos escrever:
int a = 16;
while (a--)
printf("%d\n", a); // prints numbers from 15 to 0
No entanto, gostaria de saber se verdadeiro / falso são definidos como 1
/ 0
em C, então tentei o código abaixo:
printf("True = %d, False = %d\n", (0 == 0), (0 != 0)); // prints: True = 1, False = 0
O padrão C indica explicitamente os valores verdadeiros de verdadeiro e falso como 1
e 0
respectivamente?
gcc
com-std=c89
e produz o mesmo resultado.Respostas:
O padrão C define
true
efalse
como macros nasstdbool.h
quais se expandem para1
e0
respectivamente.C11-§7.18:
Para os operadores
==
e!=
, o padrão dizC11-§6.5.9 / 3:
fonte
0 == 0
e0 != 0
etc., não sobre o valor das macros.true
ele quis dizer "o valor de uma comparação verdadeira" ou algo assim, não a macrotrue
ctrl
+f
;)NaN == NaN
é falso eNaN != NaN
é verdadeiro. Não há problema com essa afirmação.Não é indicado explicitamente em C11. Todas as operações em nível de linguagem retornarão 1 como verdadeiro (e aceitará qualquer diferente de zero incluindo NaN como verdadeiro).
_Bool
, então true deve ser 1 porque o padrão exige que ele contenha apenas 0 e 1. (§6.2.5 / 2).<stdbool.h>
macro setrue
expande para1
(§7.18 / 3)==
,!=
,<
,>
,<=
E>=
retornar 0 ou 1 (§6.5.8 / 6, §6.5.9 / 3).!
,&&
E||
retornar 0 ou 1 (§6.5.3.3 / 5, §6.5.13 / 3, §6.5.14 / 3)defined
expande para 0 ou 1 (§6.10.1 / 1)Mas todas as funções de biblioteca padrão, por exemplo,
islower
apenas diga "diferente de zero" para verdade (por exemplo, §7.4.1 / 1, §7.17.5.1 / 3, §7.30.2.1 / 1, §7.30.2.2.1 / 4).fonte
Existem duas áreas do padrão que você precisa estar ciente ao lidar com valores booleanos (pelo qual quero dizer valores verdadeiro / falso em vez do C específico
bool/_Bool
tipo ) em C.O primeiro tem a ver com o resultado de expressões e pode ser encontrado em várias partes de
C11 6.5 Expressions
(operadores relacionais e de igualdade, por exemplo). O ponto principal é que, sempre que um valor booleano é gerado por uma expressão, ele ...Portanto, sim, o resultado de qualquer expressão geradora de booleanos será um para verdadeiro ou zero para falso. Isso corresponde ao que você encontrará
stdbool.h
onde as macros padrãotrue
efalse
são definidas da mesma maneira.Tenha em mente, entretanto, que, seguindo o princípio de robustez de "ser conservador no que você envia, liberal no que você aceita", a interpretação de inteiros no contexto booleano é um pouco mais relaxada.
Novamente, em várias partes do
6.5
, você verá uma linguagem como:A partir disso (e de outras partes), é óbvio que zero é considerado falso e qualquer outro valor é verdadeiro.
Como um aparte, a linguagem que especifica qual valor é usado para a geração e interpretação booleana também aparece em C99 e C89, então eles já existem há algum tempo. Mesmo K&R (ANSI-C segunda edição e a primeira edição) especificou que, com segmentos de texto como:
As macros
stdbool.h
aparecem no C99 também, mas não no C89 ou K&R, pois o arquivo de cabeçalho não existia naquele ponto.fonte
||
,==
,!=
etc rendimentoint
, não um tipo booleanoif
,while
,for
, etc, 'verdadeiro' significa apenas 'não-zero'." Esta é a parte saliente da resposta e é, em minha opinião, uma escolha infeliz de Dennis Ritchie de muito tempo atrás. Qualquer pessoa que escreveu funções que retornam códigos de erro como o valor de retorno geralmente tem#define noErr 0
e qualquer código de erro diferente de zero é um erro. E então o problema é a simplicidade e a beleza doif ( ready_to_do_something() ){do_something();}
não funciona. Tem que serif ( !not_ready_to_do_something() ){do_something();}
"Existem muitas falsidades, mas apenas uma verdade." TRUE deve ser 0.A.7.6/7/10/11
(relacional / igualdade / lógico-e / lógico-ou) todos especificam que dá 0 ou 1 como resultado. Atualizei a resposta para incluir isso.Você está misturando muitas coisas diferentes: instruções de controle, operadores e tipos booleanos. Cada um tem suas próprias regras.
As declarações de controle funcionam como, por exemplo, a
if
declaração C11 6.4.8.1:while
,for
etc. têm a mesma regra. Isso não tem nada a ver com "verdadeiro" ou "falso".Quanto aos operadores que supostamente estão gerando um resultado booleano, eles estão gerando um
int
com valor 1 ou 0. Por exemplo, os operadores de igualdade, C11 6.5.9:Tudo isso ocorre porque C não tinha um tipo booleano até o ano de 1999 e, mesmo quando tinha um, as regras acima não foram alteradas. Portanto, ao contrário da maioria das outras linguagens de programação em que instruções e operadores geram um tipo booleano (como C ++ e Java), eles apenas geram um
int
, com valor zero ou diferente de zero. Por exemplo,sizeof(1==1)
fornecerá 4 em C, mas 1 em C ++.O tipo booleano real em C é nomeado
_Bool
e requer um compilador moderno. O cabeçalhostdbool.h
macros definebool
,true
efalse
, que se expandem para_Bool
,1
e0
respectivamente (para compatibilidade com C ++).No entanto, é considerada uma boa prática de programação tratar instruções de controle e operadores como se eles realmente exigissem / gerassem um tipo booleano. Certos padrões de codificação, como MISRA-C, recomendam essa prática. Isso é:
if(ptr == NULL)
em vez deif(ptr)
.if((data & mask) != 0)
em vez deif(data & mask)
.O objetivo desse estilo é aumentar a segurança de tipo com o auxílio de ferramentas de análise estática, que por sua vez reduzem os bugs. Indiscutivelmente, esse estilo só é significativo se você usar analisadores estáticos. Embora em alguns casos isso leve a um código mais legível e autodocumentado, por exemplo
if(c == '\0')
Ótimo, a intenção é clara, o código é autodocumentado.
versus
if(c)
Mau. Pode significar qualquer coisa, e temos que procurar o tipo de
c
para entender o código. É um número inteiro, um ponteiro ou um caractere?fonte
sizeof(bool)
é a implementação específica em C ++. Consulte stackoverflow.com/questions/4897844/is-sizeofbool-defined .if(ptr != NULL)
, ou talvezif(!ptr)
?if(c == '\0')
se presta ao erro de codificação particularmente comum para iniciantesif(c = '\0')
, então eu o evito. Concordo,if(c)
é ruim ... deveria ser, por exemplo,if(valveIsOpen)
Eu programei em várias línguas. Eu vi true ser 1 ou -1 dependendo do idioma. A lógica por trás do verdadeiro ser 1 era que um bit era 0 ou 1. A lógica por trás do verdadeiro ser -1 era que o! operador era um complemento de um. Ele mudou todos os 1's para 0's e todos os 0's para 1's em um int. Portanto, para um int,! 0 = -1 e! (- 1) = 0. Isso me enganou o suficiente para que eu não comparasse algo como == verdadeiro, mas em vez disso, comparando-o com! = Falso. Dessa forma, meu estilo de programação funciona em todas as linguagens. Portanto, minha resposta é não se preocupar com isso, mas programe para que seu código funcione corretamente de qualquer maneira.
fonte
Essa resposta precisa ser examinada um pouco mais de perto.
A definição real em C ++ é que qualquer coisa diferente de 0 é tratada como verdadeira. Por que isso é relevante? Porque C ++ não sabe o que é um inteiro pela forma como pensamos sobre ele - nós criamos esse significado, tudo o que ele contém é o shell e as regras para o que isso significa. Ele sabe o que são os bits, o que constitui um número inteiro.
1 como um inteiro é representado vagamente em bits, digamos um int assinado de 8 bits como 0000 0001. Muitas vezes o que vemos visualmente é uma mentira, -1 é uma forma muito mais comum de representá-lo devido à natureza do sinal de 'inteiro'. Eu realmente não posso significar verdadeiro, por quê? Porque NÃO é a operação 1111 1110. Esse é um problema realmente importante para um booleano. Quando falamos sobre um booleano, ele é apenas 1 bit - é realmente simples, 0 é falso e 1 é verdadeiro. Todas as operações lógicas são triviais. É por isso que '-1' deve ser designado como 'verdadeiro' para inteiros (com sinal). 1111 1111 NOT'ed torna-se 0000 0000 --- a lógica se mantém e estamos bem. Ints não assinados são um pouco complicados e eram muito mais comumente usados no passado - onde 1 significa verdadeiro porque é fácil sugerir a lógica de que '
Essa é a explicação. Eu digo que a resposta aceita aqui está errada - não há uma definição clara na definição C / C ++. Um booleano é um booleano, você pode tratar um número inteiro como um booleano, mas o fato de a saída ser um número inteiro não diz nada sobre a operação que está realmente sendo feita é bit a bit.
fonte
Aconteceu por causa dos Operadores Relacionais em seu
printf
declaração.Operador
==
e operador!=
Uma vez que
(0 == 0)
é verdade, dá um valor1
ao passo que,
(0 != 0)
não é verdade, dá um valor0
.fonte