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>
bool
o 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 bool
diferente 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.
int
para 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 int
s 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 full
vez 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 !notfull
seja 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 == b
funciona?
a
e b
conte 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, !!var
produz o valor booleano 0/1 equivalente a var
, para que você possa escrever !!a == !!b
, embora alguns leitores o achem confuso.
!a == !b
também é suficiente para testar a igualdade, não-zeros se tornam zero e zeros se tornam um.
!!a
como "converter não booleano a em seu valor de verdade equivalente", enquanto eu leria !a
como "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 true
e 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 myfalse
valor. 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
, false
e bool
sã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 -Wall
não dá avisos, então eu confio gcc
; Se isso funcionar, mesmo assim, c89
também deve funcionar c99
.
!
só pode retornar valores 0
e 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
, false
e bool
. Ou não o inclua, use e _Bool
, em vez disso.1
0
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 bool
se 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
, b
seria definido como false
iff igual a a
zero e, true
caso 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 typedef
local, o double
seria 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 true
e false
foi 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:
int
e valores 0
e 1
como está ; e faça com cuidado conversões de domínio de outros valores para esses com dupla negação!!
BOOL
, TRUE
e FALSE
!int
ou unsigned int
para 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 = 1
pelo padrão C e !a = 0
para qualquer valor diferente de zero de a
. O problema é que qualquer diferente de zero é considerado verdadeiro. Portanto, se a
e b
sã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.
bool
uma macro que se expanda para _Bool
. A diferença importa porque você pode #undef
uma macro (e isso é permitido, pelo menos como uma medida de transição), mas você não pode untypedef
digitar 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:
_Bool
ou bool
? Ambos estão bem, mas bool
parecem melhores que a palavra-chave _Bool
.bool
e _Bool
são: false
ou true
. A atribuição 0
ou em 1
vez de false
ou true
é válida, mas é mais difícil de ler e entender o fluxo lógico.Algumas informações do padrão:
_Bool
NÃO unsigned int
, mas faz parte dos tipos de números inteiros não assinados do grupo . É grande o suficiente para armazenar os valores 0
ou 1
.bool
true
e, com false
certeza, não é uma boa ideia. Essa habilidade é considerada obsoleta e será removida no futuro._Bool
ou bool
, se o valor escalar for igual 0
ou comparável a 0
ele 0
, caso contrário, o resultado é 1
: _Bool x = 9;
9
é convertido em 1
quando 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 char
que 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 _Bool
tipo Não #include
são necessários. Você precisa tratá-lo como um número inteiro, onde 1
está true
e 0
é false
.
Você pode então definir TRUE
e 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
,, true
e false
como 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 #define
diretiva 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
arg
ea 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 arg
for 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.