Eu já vi definições em C
#define TRUE (1==1)
#define FALSE (!TRUE)
Isso é necessário? Qual é o benefício de simplesmente definir TRUE como 1 e FALSE como 0?
c
precompiler
Robert Harvey
fonte
fonte
#define TRUE (’/’/’/’)
:;#define FALSE (’-’-’-’)
(extraído de coding-guidelines.com/cbook/cbook1_1.pdf página 871)Respostas:
Essa abordagem usará o
boolean
tipo real (e resolverá paratrue
efalse
) se o compilador suportar. (especificamente, C ++)No entanto, seria melhor verificar se C ++ está em uso (via
__cplusplus
macro) e realmente usartrue
efalse
.Em um compilador C, isso é equivalente a
0
e1
.(observe que remover os parênteses quebrará isso devido à ordem das operações)
fonte
1==1
é umint
. (veja stackoverflow.com/questions/7687403/... .)boolean
tipo?true
oufalse
.#define TRUE true
e#define FALSE false
sempre que__cplusplus
for definido.A resposta é portabilidade. Os valores numéricos de
TRUE
eFALSE
não são importantes. O que é importante é que uma declaração comoif (1 < 2)
avalia comoif (TRUE)
e uma declaração comoif (1 > 2)
avaliada comoif (FALSE)
.Concedido, em C,
(1 < 2)
avalia1
e(1 > 2)
avalia0
, portanto, como outros já disseram, não há diferença prática no que diz respeito ao compilador. Mas, ao permitir que o compilador definaTRUE
e deFALSE
acordo com suas próprias regras, você está explicitando seus significados aos programadores e garantindo consistência dentro do programa e de qualquer outra biblioteca (assumindo que a outra biblioteca siga os padrões C ... ser surpreendido).Alguma história
Alguns BASICs definidos
FALSE
como0
eTRUE
como-1
. Como muitas linguagens modernas, eles interpretaram qualquer valor diferente de zero comoTRUE
, mas avaliaram expressões booleanas que eram verdadeiras como-1
. SuaNOT
operação foi implementada adicionando 1 e invertendo o sinal, porque era eficiente fazê-lo dessa maneira. Então 'NOT x' se tornou-(x+1)
. Um efeito colateral disso é que um valor como5
avalia paraTRUE
, masNOT 5
avalia para-6
, o que também éTRUE
! Encontrar esse tipo de bug não é divertido.Práticas recomendadas
Dadas as regras de fato em que zero é interpretado como
FALSE
e qualquer valor diferente de zero é interpretado comoTRUE
, você nuncaTRUE
FALSE
deve comparar expressões de aparência booleana com ou . Exemplos:Por quê? Porque muitos programadores usam o atalho para tratar
int
s comobool
s. Eles não são os mesmos, mas os compiladores geralmente permitem. Por exemplo, é perfeitamente legal escreverQue aparência legítimos, e o compilador terá todo o prazer aceitá-lo, mas ele provavelmente não faz o que você gostaria. Isso porque o valor de retorno de
strcmp()
é0 se
yourString == myString
<0 se
yourString < myString
> 0 se
yourString > myString
Portanto, a linha acima retorna
TRUE
apenas quandoyourString > myString
.A maneira correta de fazer isso é
ou
Similarmente:
Você encontrará frequentemente alguns desses "exemplos ruins" no código de produção, e muitos programadores experientes juram por eles: eles funcionam, alguns são mais curtos que suas alternativas corretas (pedanticamente?) E os idiomas são quase universalmente reconhecidos. Mas considere: as versões "certas" não são menos eficientes, são garantidas para serem portáteis, elas passam pelos linters mais rígidos e até mesmo os novos programadores as entendem.
Isso não vale a pena?
fonte
(1==1)
não é mais portátil do que1
. As regras do próprio compilador são as da linguagem C, que é clara e inequívoca sobre a semântica da igualdade e dos operadores relacionais. Eu nunca vi um compilador errar essas coisas.strcmp
sabe-se que o valor retornado por é menor que, igual ou maior que 0. Não é garantido que seja -1, 0 ou 1 e existem plataformas em estado selvagem que não retornam esses valores para ganhar velocidade de implementação. Então, sestrcmp(a, b) == TRUE
, em seguida,a > b
mas inversa implicação não pôde prender.(1==1)
e1
são expressões constantes do tipoint
com o valor 1. Elas são semanticamente idênticas. Suponho que você possa escrever um código que atenda a leitores que não sabem disso, mas onde termina?O
(1 == 1)
truque é útil para definirTRUE
de uma maneira que seja transparente para C, mas que ofereça melhor digitação em C ++. O mesmo código pode ser interpretado como C ou C ++ se você estiver escrevendo em um dialeto chamado "Clean C" (que é compilado como C ou C ++) ou se estiver gravando arquivos de cabeçalho de API que possam ser usados por programadores de C ou C ++.Nas unidades de tradução C,
1 == 1
tem exatamente o mesmo significado que1
; e1 == 0
tem o mesmo significado que0
. No entanto, no C ++ unidades de tradução,1 == 1
tem tipobool
. Portanto, aTRUE
macro definida dessa maneira se integra melhor ao C ++.Um exemplo de como ele se integra melhor é que, por exemplo, se a função
foo
tiver sobrecargas paraint
e parabool
, entãofoo(TRUE)
ela escolherá abool
sobrecarga. SeTRUE
for apenas definido como1
, não funcionará bem no C ++.foo(TRUE)
vai querer aint
sobrecarga.Claro, C99 introduzida
bool
,true
efalse
e estes podem ser usados em arquivos de cabeçalho que o trabalho com C99 e com C.Contudo:
TRUE
eFALSE
como(0==0)
e(1==0)
antecede C99.Se você estiver trabalhando em um projeto misto de C e C ++ e não quiser o C99, defina as letras minúsculas e
true
, em vez disso.false
bool
Dito isto, o
0==0
truque foi (é?) Usado por alguns programadores, mesmo em código que nunca teve a intenção de interoperar com o C ++ de forma alguma. Isso não compra nada e sugere que o programador tem um mal-entendido de como os booleanos funcionam em C.Caso a explicação do C ++ não esteja clara, aqui está um programa de teste:
A saída:
Quanto à pergunta dos comentários de como as funções C ++ sobrecarregadas são relevantes para a programação mista de C e C ++. Isso apenas ilustra uma diferença de tipo. Um motivo válido para desejar que uma
true
constante sejabool
compilada como C ++ é o diagnóstico limpo. Nos níveis mais altos de aviso, um compilador C ++ pode nos alertar sobre uma conversão se passarmos um número inteiro comobool
parâmetro. Uma razão para escrever no Clean C não é apenas o fato de nosso código ser mais portátil (já que é entendido pelos compiladores C ++, não apenas pelos compiladores C), mas também podemos nos beneficiar das opiniões de diagnóstico dos compiladores C ++.fonte
TRUE
serão diferentes em C ++.#ifdef __cplusplus
para expressar sua intenção com muito mais clareza.bool
eint
não importam muito na prática, pois são implicitamente conversíveis entre si (e em C, na verdade, "o mesmo" , observe as aspas , no entanto) e não há muitas situações nas quais você realmente precisa desambiguar as duas. "não muito" provavelmente foi muito pesado " , muito menos se comparado ao código que usa modelos e sobrecarga" teria sido melhor talvez.é equivalente a
em C.
O resultado dos operadores relacionais é
0
ou1
.1==1
é garantido para ser avaliado1
e!(1==1)
garantido para ser avaliado0
.Não há absolutamente nenhuma razão para usar a primeira forma. Observe que a primeira forma não é menos eficiente, pois em quase todos os compiladores uma expressão constante é avaliada no tempo de compilação e não no tempo de execução. Isso é permitido de acordo com esta regra:
O PC-Lint emitirá uma mensagem (506, valor constante booleano) se você não usar um literal para
TRUE
eFALSE
macros:Também em C99, as
stdbool.h
definições para macros booleanastrue
efalse
usam diretamente literais:fonte
1==1
é garantido para ser avaliado para1
if(foo == true)
, que passará de meramente má prática a um buggy simples.(x == TRUE)
pode ter um valor de verdade diferente dex
.Além do C ++ (já mencionado), outro benefício é para ferramentas de análise estática. O compilador eliminará quaisquer ineficiências, mas um analisador estático pode usar seus próprios tipos abstratos para distinguir entre resultados de comparação e outros tipos inteiros; portanto, sabe implicitamente que TRUE deve ser o resultado de uma comparação e não deve ser considerado compatível. com um número inteiro.
Obviamente, C diz que eles são compatíveis, mas você pode optar por proibir o uso deliberado desse recurso para ajudar a destacar bugs - por exemplo, onde alguém pode ter se confundido
&
e&&
/ ou eles confundiram sua precedência de operador.fonte
if (boolean_var == TRUE)
por meio de expansão para aif (boolean_var == (1 == 1))
qual, graças às informações aprimoradas de tipo do(1 == 1)
nó, caiam no padrãoif (<*> == <boolean_expr>)
.A diferença prática é nenhuma.
0
é avaliadofalse
e1
avaliado comotrue
. O fato de você usar uma expressão booleana (1 == 1
) ou1
, para definirtrue
, não faz diferença. Ambos são avaliados paraint
.Note-se que a biblioteca padrão C proporciona um cabeçalho específico para definir booleanos:
stdbool.h
.fonte
true
é avaliado1
efalse
avaliado como0
. C não sabe sobre tipos booleanos nativos, são apenas ints.int
, com valor0
ou1
. C tem um tipo booleano real (_Bool
com um macrobool
definido no<stdbool.h>
, mas que só foi adicionada no C99, que se não mudar a semântica dos operadores para usar o novo tipo._Bool
, e<stdbool.h>
tem#define bool _Bool
.1 == 1
ser avaliado comoint
. Editado.Não sabemos o valor exato que TRUE é igual e os compiladores podem ter suas próprias definições. Então, o que você privode é usar o interno do compilador para definição. Isso nem sempre é necessário se você tiver bons hábitos de programação, mas puder evitar problemas por algum estilo de codificação ruim, por exemplo:
if ((a> b) == VERDADEIRO)
Isso pode ser um desastre se você definir manualmente TRUE como 1, enquanto o valor interno de TRUE for outro.
fonte
>
operador sempre produz 1 para verdadeiro, 0 para falso. Não há possibilidade de nenhum compilador C estar errado. Comparações de igualdadeTRUE
eFALSE
estilo pobre; o acima é mais claramente escrito comoif (a > b)
. Mas a idéia de que diferentes compiladores C podem tratar a verdade e o falso de maneira diferente é incorreta.Normalmente, na linguagem de programação C, 1 é definido como verdadeiro e 0 é definido como falso. Por isso, você vê o seguinte com bastante frequência:
No entanto, qualquer número diferente de 0 seria avaliado como verdadeiro também em uma instrução condicional. Portanto, usando o abaixo:
Você pode apenas mostrar explicitamente que está tentando jogar pelo seguro, tornando falso igual ao que não é verdadeiro.
fonte