Usando valores booleanos em C

C não possui nenhum tipo booleano embutido. Qual é a melhor maneira de usá-los em C?

Opção 1

typedef int bool; #define true 1 #define false 0 

opção 2

 typedef int bool; enum { false, true }; 

Opção 3

 typedef enum { false, true } bool; 

Opção 4 (C99)

 #include  

Explicação

  • As opções 1, 2 e 3 terão, na prática, o mesmo comportamento idêntico. # 2 e # 3 não usam # define, o que na minha opinião é melhor.
  • Opção 4 funcionará somente se você usar C99 e é o “modo padrão” para fazê-lo. Escolha isto se possível.

Se você está indeciso, vá com # 3!

Algumas reflexões sobre booleanos em C:

Eu tenho idade suficiente para usar apenas int s como meu tipo booleano sem nenhum typedefs ou especial define ou enums para valores true / false. Se você seguir minha sugestão abaixo em nunca comparar com constantes booleanas, então você só precisa usar 0/1 para inicializar as flags de qualquer maneira. No entanto, tal abordagem pode ser considerada muito reacionária nestes tempos modernos. Nesse caso, deve-se definitivamente usar pois pelo menos tem o benefício de ser padronizado.

Quaisquer que sejam as constantes booleanas, use-as apenas para boot. Nunca, nunca escreva algo como

 if (ready == TRUE) ... while (empty == FALSE) ... 

Estes sempre podem ser substituídos pelo mais claro

 if (ready) ... while (!empty) ... 

Note-se que estes podem realmente razoavelmente e compreensivelmente ser lido em voz alta.

Dê a suas variables ​​booleanas nomes positivos, isto é, full vez de notfull . O último leva a um código difícil de ler com facilidade. Comparar

 if (full) ... if (!full) ... 

com

 if (!notfull) ... if (notfull) ... 

Ambos os pares anteriores são lidos naturalmente, enquanto que !notfull é difícil de ler mesmo como é, e se torna muito pior em expressões booleanas mais complexas.

Argumentos booleanos geralmente devem ser evitados. Considere uma function definida como esta

 void foo(bool option) { ... } 

Dentro do corpo da function, é muito claro o que o argumento significa, uma vez que ele tem um nome conveniente e esperançosamente significativo. Mas, os sites de chamada parecem

 foo(TRUE); foo(FALSE): 

Aqui, é essencialmente impossível dizer o que o parâmetro significa sem sempre olhar para a definição ou declaração da function, e fica muito pior assim que você adiciona ainda mais parâmetros booleanos. Eu sugiro

 typedef enum { OPT_ON, OPT_OFF } foo_option; void foo(foo_option option); 

ou

 #define OPT_ON true #define OPT_OFF false void foo(bool option) { ... } 

Em qualquer casee, o site de chamadas agora parece

 foo(OPT_ON); foo(OPT_OFF); 

que o leitor tenha pelo menos uma chance de entender sem ter que definir a definição de foo .

Um booleano em C é um inteiro: zero para falso e diferente de zero para verdadeiro.

Veja também tipo de dados booleano , seção C, C ++, Objective-C, AWK .

Aqui está a versão que eu usei:

 typedef enum { false = 0, true = !false } bool; 

Porque false tem apenas um valor, mas um true lógico pode ter muitos valores, mas conjuntos de técnica true para ser o que o compilador usará para o oposto de false.

Isso cuida do problema de alguém codificar algo que se resume a isso:

 if (true == !false) 

Acho que todos concordamos que isso não é uma boa prática, mas pelo custo de fazer “true =! False” eliminamos esse problema.

[EDITAR] No final eu usei:

 typedef enum { myfalse = 0, mytrue = !myfalse } mybool; 

para evitar a colisão de nomes com outros esquemas que estavam definindo true e false . Mas o conceito continua o mesmo.

[EDIT] Para mostrar a conversão de inteiro para booleano:

 mybool somebool; int someint = 5; somebool = !!someint; 

O primeiro (mais à direita)! converte o inteiro diferente de zero em 0, depois o segundo (mais à esquerda)! converte o 0 em um valor myfalse . Deixarei como um exercício para o leitor converter um inteiro zero.

Se você estiver usando um compilador C99, ele terá suporte embutido para tipos de bool:

 #include  int main() { bool b = false; b = true; } 

http://en.wikipedia.org/wiki/Boolean_data_type

 typedef enum { false = 0, true } t_bool; 

C tem um tipo booleano: bool (pelo menos nos últimos 10 (!) Anos)

Incluir stdbool.he verdadeiro / falso funcionará como esperado.

Qualquer coisa diferente de zero é avaliada como verdadeira em operações booleanas, então você poderia

 #define TRUE 1 #define FALSE 0 

e use as constantes.

Primeiras coisas primeiro. C, ou seja, a ISO / IEC 9899 tem um tipo booleano há 19 anos . Isso é muito mais tempo do que a duração esperada da carreira de programação C com partes amadoras / acadêmicas / profissionais combinadas ao visitar esta questão . O meu supera isso por meros talvez 1-2 anos. No entanto, durante o tempo em que um leitor médio aprendeu alguma coisa sobre C, C realmente teve o tipo de dados booleano .

Para o tipo de dados, #include e use true , false e bool . Ou não inclua e use _True , _False e _Bool .


Existem vários conselhos perigosos neste tópico de resposta. Eu vou abordá-los:

 typedef int bool; #define true 1 #define false 0 

Isso é não-não, porque um leitor casual – que aprendeu C dentro desses 19 anos – esperaria que bool se bool ao tipo de dado bool e se comportaria de maneira semelhante, mas isso não acontece! Por exemplo

 double a = ...; bool b = a; 

Com bool / _Bool C99, b seria definido como false se a era zero e true caso contrário. Com o typedef no lugar, o double seria coagido para um int – se o valor do double não estiver no intervalo para int int, o comportamento é indefinido .

Naturalmente, o mesmo se aplica se true e false forem declarados em um enum .

O que é ainda mais perigoso é declarar

 typedef enum bool { false, true } bool; 

porque agora todos os valores além de 1 e 0 são inválidos, e se tal valor fosse atribuído a uma variável daquele tipo, o comportamento seria totalmente indefinido .

Portanto, se você não pode usar o C99 por alguma razão inexplicável, para variables ​​booleanas você deve usar:

  • digite int e valores 0 e 1 como estão ; e cuidadosamente faça conversões de domínio de quaisquer outros valores para estes com dupla negação !!
  • ou se você insiste que não lembra que 0 é falsamente e não-zero verdade, pelo menos use letras maiúsculas para que elas não se confundam com os conceitos do C99: BOOL , TRUE e FALSE !

@ Thomas Matthews: As expressões condicionais são consideradas verdadeiras se forem diferentes de zero, mas o padrão C exige que os próprios operadores lógicos retornem 0 ou 1.

@ Tom: #define TRUE! FALSE é ruim e é completamente inútil. Se o arquivo de header chegar ao código C ++ compilado, ele poderá causar problemas:

 void foo(bool flag); ... int flag = TRUE; foo(flag); 

Alguns compiladores geram um aviso sobre a conversão int => bool. Às vezes as pessoas evitam isso fazendo:

 foo(flag == TRUE); 

para forçar a expressão a ser um bool C ++. Mas se você definir DEFINE TRUE! FALSE, você acaba com:

 foo(flag == !0); 

que acaba fazendo uma comparação int-to-bool que pode acionar o aviso de qualquer maneira.

Você pode usar um caractere ou outro contêiner de pequeno número para ele.

Pseduo

 #define TRUE 1 #define FALSE 0 char bValue = TRUE; 

É isto:

 #define TRUE 1 #define FALSE 0 

Você pode simplesmente usar a diretiva #define da seguinte maneira:

 #define TRUE 1 #define FALSE 0 #define NOT(arg) (arg == TRUE)? FALSE : TRUE typedef int bool; 

E use da seguinte maneira:

 bool isVisible = FALSE; bool isWorking = TRUE; isVisible = NOT(isVisible); 

e assim por diante