C não possui nenhum tipo booleano interno. Qual é a melhor maneira de usá-los em C?
C não possui nenhum tipo booleano interno. Qual é a melhor maneira de usá-los em C?
Respostas:
Do melhor ao pior:
Opção 1 (C99)
#include <stdbool.h>
opção 2
typedef enum { false, true } bool;
Opção 3
typedef int bool;
enum { false, true };
Opção 4
typedef int bool;
#define true 1
#define false 0
Se você estiver indeciso, vá com o número 1!
<stdbool.h> boolo compilador escolhe pode ser mais adequado para a finalidade pretendida de um valor booleano do que utilizar um int(isto é, o compilador pode optar por implementar um booldiferente do que um int). Também pode resultar em uma verificação mais rigorosa do tipo no momento da compilação, se você tiver sorte.
intpara bool? Isso é um desperdício. Use unsigned char. Ou use o C embutido _Bool.
Algumas reflexões sobre os booleanos em C:
Tenho idade suficiente para usar apenas plain ints como meu tipo booleano, sem nenhum typedefs ou definições ou enumerações especiais para valores true / false. Se você seguir minha sugestão abaixo, nunca comparando com constantes booleanas, precisará usar 0/1 para inicializar os sinalizadores de qualquer maneira. No entanto, essa abordagem pode ser considerada muito reacionária nos tempos modernos. Nesse caso, deve-se definitivamente usar, <stdbool.h>pois pelo menos tem o benefício de ser padronizado.
Quaisquer que sejam as constantes booleanas chamadas, use-as apenas para inicialização. Nunca escreva algo como
if (ready == TRUE) ...
while (empty == FALSE) ...
Estes sempre podem ser substituídos pelos mais claros
if (ready) ...
while (!empty) ...
Observe que eles podem ser lidos em voz alta e razoável.
Atribua nomes positivos às suas variáveis booleanas, ou seja, em fullvez de notfull. O último leva a um código difícil de ler facilmente. Comparar
if (full) ...
if (!full) ...
com
if (!notfull) ...
if (notfull) ...
Ambos os pares anteriores lêem naturalmente, embora !notfullseja difícil ler o que é, e se tornam muito piores em expressões booleanas mais complexas.
Argumentos booleanos geralmente devem ser evitados. Considere uma função definida como esta
void foo(bool option) { ... }
Dentro do corpo da função, é muito claro o que o argumento significa, uma vez que possui um nome conveniente e, espero, significativo. Mas, os sites de chamada parecem
foo(TRUE);
foo(FALSE):
Aqui, é essencialmente impossível dizer o que o parâmetro significou sem sempre olhar para a definição ou declaração da função, e fica muito pior assim se você adicionar 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 ambos os casos, o site de chamada agora parece
foo(OPT_ON);
foo(OPT_OFF);
que o leitor tem pelo menos uma chance de entender sem aprofundar a definição de foo.
a == bfunciona?
ae bconte a partir de zero, eu recomendo a > 0 == b > 0. Se você insistir em tirar proveito da veracidade de valores arbitrários diferentes de zero, !!varproduz o valor booleano 0/1 equivalente a var, para que você possa escrever !!a == !!b, embora alguns leitores o achem confuso.
!a == !btambém é suficiente para testar a igualdade, não-zeros se tornam zero e zeros se tornam um.
!!acomo "converter não booleano a em seu valor de verdade equivalente", enquanto eu leria !acomo "inverter logicamente a variável booleana a". Em particular, eu procuraria por algum motivo específico que a inversão lógica fosse desejada.
Um booleano em C é um número inteiro: zero para falso e diferente de zero para verdadeiro.
Consulte também Tipo de dados booleanos , seção C, C ++, Objective-C, AWK .
Aqui está a versão que eu usei:
typedef enum { false = 0, true = !false } bool;
Como false possui apenas um valor, mas um true lógico pode ter muitos valores, mas a técnica define true para ser o que o compilador usará para o oposto de false.
Isso resolve o problema de alguém codificar algo que se resume a isso:
if (true == !false)
Acho que todos concordamos que essa não é uma boa prática, mas pelo custo único de se fazer "verdadeiro =! Falso", eliminamos esse problema.
[EDIT] No final, eu usei:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
para evitar colisão de nomes com outros esquemas que estavam definindo truee false. Mas o conceito permanece o mesmo.
[EDIT] Para mostrar a conversão de número inteiro em booleano:
mybool somebool;
int someint = 5;
somebool = !!someint;
O primeiro (mais à direita)! converte o número inteiro diferente de zero em 0, depois o segundo (mais à esquerda)! converte o 0 em um myfalsevalor. Vou deixar como um exercício para o leitor converter um número inteiro zero.
[EDIT] É meu estilo usar a configuração explícita de um valor em uma enumeração quando o valor específico é necessário, mesmo que o valor padrão seja o mesmo. Exemplo: como false precisa ser zero, eu uso em false = 0,vez defalse,
true, falsee boolsão destacadas em, porque eles são valores enum e um typedef, ao contrário da maioria IDE #defines, que são raramente sintaxe destacada.
gcc -ansi -pedantic -Wallnão dá avisos, então eu confio gcc; Se isso funcionar, mesmo assim, c89também deve funcionar c99.
!só pode retornar valores 0e 1, portanto true = !false, sempre atribuirá o valor 1. Este método não oferece segurança extra typedef enum { false, true } bool;.
if(!value)), mas essa exceção não é aplicável neste caso específico.
Se você estiver usando um compilador C99, ele possui suporte interno para tipos de bool:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}
Primeiras coisas primeiro. C, ou seja, a ISO / IEC 9899 possui 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 pergunta . A minha supera isso em meros talvez 1-2 anos. Isso significa que, durante o tempo em que um leitor comum aprendeu alguma coisa sobre C, C realmente teve o tipo de dados booleanos .
Para o tipo de dados,, #include <stdbool.h>e use true, falsee bool. Ou não o inclua, use e _Bool, em vez disso.10
Existem várias práticas perigosas promovidas nas outras respostas a este segmento. Vou abordá-los:
typedef int bool;
#define true 1
#define false 0
Isso é não-não, porque um leitor casual - que aprendeu C nesses 19 anos - esperaria que isso boolse refere ao tipo de dados real bool e se comportaria de maneira semelhante, mas não! Por exemplo
double a = ...;
bool b = a;
Com C99 bool/ _Bool, bseria definido como false iff igual a a zero e, truecaso contrário. C11 6.3.1.2p1
- Quando qualquer valor escalar é convertido em
_Bool, o resultado é 0 se o valor for comparado a 0; caso contrário, o resultado é 1. 59)Notas de rodapé
59) NaNs não comparam igual a 0 e, portanto, convertem para 1.
Com o typedeflocal, o doubleseria coagido a um int- se o valor do dobro não estiver no intervalo int, o comportamento será indefinido .
Naturalmente, o mesmo se aplica a se truee falsefoi declarado 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 esse valor for atribuído a uma variável desse tipo, o comportamento será totalmente indefinido .
Portanto, se você não pode usar C99 por algum motivo inexplicável, para variáveis booleanas você deve usar:
inte valores 0e 1 como está ; e faça com cuidado conversões de domínio de outros valores para esses com dupla negação!!BOOL, TRUEe FALSE!intou unsigned intpara armazenar uma enumeração, mas não conheço nada no Padrão que faça com que uma enumeração se comporte como algo diferente de um número inteiro. tipo.
typedef enum {
false = 0,
true
} t_bool;
!0 = 1pelo padrão C e !a = 0para qualquer valor diferente de zero de a. O problema é que qualquer diferente de zero é considerado verdadeiro. Portanto, se ae bsão "verdadeiros", não é necessariamente o caso que `a == b`.
C tem um tipo booleano: bool (pelo menos nos últimos 10 (!) Anos)
Inclua stdbool.he true / false funcionará conforme o esperado.
booluma macro que se expanda para _Bool. A diferença importa porque você pode #undefuma macro (e isso é permitido, pelo menos como uma medida de transição), mas você não pode untypedefdigitar um. No entanto, isso não altera o impulso principal do seu primeiro comentário.
Qualquer coisa diferente de zero é avaliada como verdadeira em operações booleanas, para que você possa apenas
#define TRUE 1
#define FALSE 0
e use as constantes.
Apenas um complemento para outras respostas e alguns esclarecimentos, se você puder usar o C99.
+-------+----------------+-------------------------+--------------------+
| Name | Characteristic | Dependence in stdbool.h | Value |
+-------+----------------+-------------------------+--------------------+
| _Bool | Native type | Don't need header | |
+-------+----------------+-------------------------+--------------------+
| bool | Macro | Yes | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
| true | Macro | Yes | Translate to 1 |
+-------+----------------+-------------------------+--------------------+
| false | Macro | Yes | Translate to 0 |
+-------+----------------+-------------------------+--------------------+
Algumas das minhas preferências:
_Boolou bool? Ambos estão bem, mas boolparecem melhores que a palavra-chave _Bool.boole _Boolsão: falseou true. A atribuição 0ou em 1vez de falseou trueé válida, mas é mais difícil de ler e entender o fluxo lógico.Algumas informações do padrão:
_BoolNÃO unsigned int, mas faz parte dos tipos de números inteiros não assinados do grupo . É grande o suficiente para armazenar os valores 0ou 1.bool truee, com falsecerteza, não é uma boa ideia. Essa habilidade é considerada obsoleta e será removida no futuro._Boolou bool, se o valor escalar for igual 0ou comparável a 0ele 0, caso contrário, o resultado é 1: _Bool x = 9; 9é convertido em 1quando atribuído a x._Boolé de 1 byte (8 bits), geralmente o programador é tentado a tentar usar os outros bits, mas não é recomendado, porque a única garantia garantida é que apenas um bit seja usado para armazenar dados, não como o tipo charque possui 8 bits . bits disponíveis.Você pode usar um caractere ou outro contêiner de número pequeno.
Pseudo-código
#define TRUE 1
#define FALSE 0
char bValue = TRUE;
int), já que em algumas arquiteturas você obtém um desempenho significativo ao ter que descompactar / mascarar as verificações dessas variáveis.
Você pode usar _Bool, mas o valor de retorno deve ser um número inteiro (1 para true, 0 para false). No entanto, recomenda-se incluir e usar bool como em C ++, como foi dito nesta resposta do fórum daniweb , bem como nesta resposta , desta outra pergunta sobre o stackoverflow:
_Bool: tipo booleano do C99. Usar o _Bool diretamente é recomendado apenas se você estiver mantendo um código legado que já define macros para bool, true ou false. Caso contrário, essas macros são padronizadas no cabeçalho. Inclua esse cabeçalho e você pode usar bool como faria em C ++.
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: #definir VERDADEIRO! FALSO é ruim e é completamente inútil. Se o arquivo de cabeçalho chegar ao código C ++ compilado, poderá causar problemas:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
Alguns compiladores irão gerar 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 booleano C ++. Mas se você definir # VERDADEIRO! FALSO, terá:
foo(flag == !0);
que acaba fazendo uma comparação int-bool que pode disparar o aviso de qualquer maneira.
Se você estiver usando o C99, poderá usar o _Booltipo Não #includesão necessários. Você precisa tratá-lo como um número inteiro, onde 1está truee 0é false.
Você pode então definir TRUEe FALSE.
_Bool this_is_a_Boolean_var = 1;
//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;
#include <stdbool.h>e usar bool,, truee falsecomo o padrão deseja.
Isto é o que eu uso:
enum {false, true};
typedef _Bool bool;
_Bool é um tipo incorporado em C. Destina-se a valores booleanos.
Você pode simplesmente usar a #definediretiva 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
argea expressão como um todo: #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE). No entanto, seria melhor testar a falsidade (ela fornecerá a resposta correta mesmo se argfor 23 em vez de 0 ou 1 : #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE). Mas toda a expressão pode ser reduzida a #define NOT(arg) (!(arg)), é claro, que produz o mesmo resultado.