He visto definiciones en C
#define TRUE (1==1)
#define FALSE (!TRUE)
¿Es esto necesario? ¿Cuál es el beneficio sobre simplemente definir VERDADERO como 1 y FALSO como 0?
c
precompiler
Robert Harvey
fuente
fuente
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(tomado de coding-guidelines.com/cbook/cbook1_1.pdf página 871)Respuestas:
Este enfoque utilizará el
boolean
tipo real (y resolverátrue
yfalse
) si el compilador lo admite. (específicamente, C ++)Sin embargo, sería mejor verificar si C ++ está en uso (a través de la
__cplusplus
macro) y realmente usartrue
yfalse
.En un compilador de C, esto es equivalente a
0
y1
.(tenga en cuenta que eliminar los paréntesis lo romperá debido al orden de las operaciones)
fuente
1==1
es unint
. (ver stackoverflow.com/questions/7687403/… .)boolean
tipo?true
ofalse
.#define TRUE true
y#define FALSE false
siempre que__cplusplus
esté definido.La respuesta es la portabilidad. Los valores numéricos de
TRUE
yFALSE
no son importantes. Lo que es importante es que una afirmación comoif (1 < 2)
se evalúa enif (TRUE)
y una declaración comoif (1 > 2)
evalúa aif (FALSE)
.Por supuesto, en C,
(1 < 2)
evalúa1
y(1 > 2)
evalúa a0
, por lo que, como han dicho otros, no hay una diferencia práctica en lo que respecta al compilador. Pero al permitir que el compilador definaTRUE
y deFALSE
acuerdo con sus propias reglas, está haciendo que sus significados sean explícitos para los programadores, y está garantizando la coherencia dentro de su programa y cualquier otra biblioteca (suponiendo que la otra biblioteca siga los estándares C ... estar asombrado).Alguna historia
Algunos BASICs definidos
FALSE
como0
yTRUE
como-1
. Al igual que muchos lenguajes modernos, interpretaron cualquier valor distinto de cero comoTRUE
, pero evaluaron expresiones booleanas que eran verdaderas como-1
. SuNOT
operación se implementó agregando 1 y volteando el signo, porque era eficiente hacerlo de esa manera. Entonces se convirtió en 'NO x'-(x+1)
. Un efecto secundario de esto es que un valor como5
evalúa aTRUE
, peroNOT 5
evalúa a-6
, ¡que también lo esTRUE
! Encontrar este tipo de error no es divertido.Mejores prácticas
Dadas las de facto reglas que cero se interpreta como
FALSE
y cualquier valor distinto de cero se interpreta comoTRUE
, usted debe nunca se comparen las expresiones booleanas de aspecto aTRUE
oFALSE
. Ejemplos:¿Por qué? Porque muchos programadores usan el atajo de tratar
int
s comobool
s. No son lo mismo, pero los compiladores generalmente lo permiten. Entonces, por ejemplo, es perfectamente legal escribirEso parece legítimo, y el compilador lo aceptará felizmente, pero probablemente no haga lo que quieras. Eso es porque el valor de retorno de
strcmp()
es0 si
yourString == myString
<0 si
yourString < myString
> 0 si
yourString > myString
Entonces la línea de arriba
TRUE
solo regresa cuandoyourString > myString
.La forma correcta de hacer esto es
o
Similar:
A menudo encontrará algunos de estos "malos ejemplos" en el código de producción, y muchos programadores experimentados juran por ellos: funcionan, algunos son más cortos que sus alternativas correctas (¿pedante?) Y los modismos son casi universalmente reconocidos. Pero considere: las versiones "correctas" no son menos eficientes, están garantizadas para ser portátiles, pasarán incluso las cartas más estrictas e incluso los nuevos programadores las entenderán.
¿No vale eso?
fuente
(1==1)
No es más portátil que1
. Las propias reglas del compilador son las del lenguaje C, que es claro e inequívoco sobre la semántica de la igualdad y los operadores relacionales. Nunca he visto a un compilador interpretar mal estas cosas.strcmp
se sabe que el valor devuelto por es menor, igual o mayor que 0. No se garantiza que sea -1, 0 o 1 y hay plataformas en la naturaleza que no devuelven esos valores para ganar velocidad de implementación. Entonces, si esstrcmp(a, b) == TRUE
así,a > b
pero la implicación inversa podría no ser válida.(1==1)
y1
ambas son expresiones constantes de tipoint
con el valor 1. Son semánticamente idénticas. Supongo que puedes escribir código que se dirija a lectores que no lo saben, pero ¿dónde termina?El
(1 == 1)
truco es útil para definirTRUE
de una manera que sea transparente para C, pero que proporcione una mejor escritura en C ++. El mismo código puede interpretarse como C o C ++ si está escribiendo en un dialecto llamado "Clean C" (que se compila como C o C ++) o si está escribiendo archivos de encabezado de API que pueden ser utilizados por programadores de C o C ++.En las unidades de traducción C,
1 == 1
tiene exactamente el mismo significado que1
; y1 == 0
tiene el mismo significado que0
. Sin embargo, en las unidades de traducción de C ++,1 == 1
tiene tipobool
. Entonces laTRUE
macro definida de esa manera se integra mejor en C ++.Un ejemplo de cómo se integra mejor es que, por ejemplo, si la función
foo
tiene sobrecargas porint
y parabool
, entoncesfoo(TRUE)
elegirá labool
sobrecarga. SiTRUE
solo se define como1
, entonces no funcionará bien en C ++.foo(TRUE)
querrá laint
sobrecarga.Por supuesto, C99 introdujo
bool
,true
yfalse
y estos se pueden utilizar en los archivos de cabecera que trabajan con C99 y con C.Sin embargo:
TRUE
yFALSE
como(0==0)
y(1==0)
predates C99.Si está trabajando en un proyecto de C mixta y C ++, y no desea C99, definir el menor de los casos
true
,false
ybool
en su lugar.Dicho esto, el
0==0
truco fue (¿es?) Utilizado por algunos programadores incluso en código que nunca tuvo la intención de interactuar con C ++ de ninguna manera. Eso no compra nada y sugiere que el programador tiene un malentendido sobre cómo funcionan los booleanos en C.En caso de que la explicación de C ++ no fuera clara, aquí hay un programa de prueba:
La salida:
En cuanto a la pregunta de los comentarios sobre cómo se sobrecargan las funciones de C ++ relevantes para la programación mixta de C y C ++. Estos solo ilustran una diferencia de tipo. Una razón válida para querer una
true
constantebool
cuando se compila como C ++ es para un diagnóstico limpio. En sus niveles de advertencia más altos, un compilador de C ++ podría advertirnos sobre una conversión si pasamos un entero comobool
parámetro. Una razón para escribir en Clean C no es solo que nuestro código es más portátil (ya que los compiladores de C ++ lo entienden, no solo los compiladores de C), sino que podemos beneficiarnos de las opiniones de diagnóstico de los compiladores de C ++.fuente
TRUE
diferirán en C ++.#ifdef __cplusplus
para expresar su intención con mucha más claridad.bool
yint
no importan mucho en la práctica, ya que son implícitamente convertibles entre sí (y en C en realidad "lo mismo" , tenga en cuenta las citas , sin embargo) y no hay muchas situaciones en las que realmente necesite desambiguar entre los dos. "no mucho" probablemente era demasiado pesado, "mucho menos en comparación con el código que usa plantillas y sobrecarga" quizás hubiera sido mejor.es equivalente a
C ª.
El resultado de los operadores relacionales es
0
o1
.1==1
está garantizado para ser evaluado1
y!(1==1)
está garantizado para ser evaluado0
.No hay absolutamente ninguna razón para usar la primera forma. Sin embargo, tenga en cuenta que la primera forma no es menos eficiente, ya que en casi todos los compiladores se evalúa una expresión constante en tiempo de compilación en lugar de en tiempo de ejecución. Esto está permitido de acuerdo con esta regla:
PC-Lint incluso emitirá un mensaje (506, valor booleano constante) si no utiliza un literal para
TRUE
yFALSE
macros:También en C99, las
stdbool.h
definiciones de macros booleanastrue
yfalse
directamente usan literales:fuente
1==1
está garantizado para ser evaluado a1
if(foo == true)
, que pasará de ser simplemente una mala práctica a un buggy plano.(x == TRUE)
puede tener un valor de verdad diferente quex
.Aparte de C ++ (ya mencionado), otro beneficio es para las herramientas de análisis estático. El compilador eliminará cualquier ineficiencia, pero un analizador estático puede usar sus propios tipos abstractos para distinguir entre resultados de comparación y otros tipos enteros, por lo que sabe implícitamente que VERDADERO debe ser el resultado de una comparación y no debe suponerse que es compatible. con un entero
Obviamente, C dice que son compatibles, pero puede optar por prohibir el uso deliberado de esa función para ayudar a resaltar errores, por ejemplo, dónde alguien podría haber confundido
&
y&&
/ o haber confundido su precedencia de operador.fuente
if (boolean_var == TRUE)
través de una expansión a laif (boolean_var == (1 == 1))
cual, gracias a la información de tipo mejorada del(1 == 1)
nodo, se incluye en el patrónif (<*> == <boolean_expr>)
.La diferencia práctica es ninguna.
0
se evalúafalse
y1
se evalúa entrue
. El hecho de que use una expresión booleana (1 == 1
) o1
, para definirtrue
, no hace ninguna diferencia. Ambos son evaluados paraint
.Tenga en cuenta que la biblioteca estándar de C proporciona una cabecera específica para definir booleanos:
stdbool.h
.fuente
true
se evalúa1
yfalse
se evalúa en0
. C no sabe acerca de los tipos booleanos nativos, son solo ints.int
, con valor0
o1
. C tiene un tipo booleano real (_Bool
con una macrobool
definida en<stdbool.h>
, pero eso solo se agregó en C99, lo que no cambió la semántica de los operadores para usar el nuevo tipo._Bool
y<stdbool.h>
tiene#define bool _Bool
.1 == 1
evaluación comoint
. EditadoNo sabemos el valor exacto al que TRUE es igual y los compiladores pueden tener sus propias definiciones. Entonces, lo que usted privilegia es usar el interno del compilador para la definición. Esto no siempre es necesario si tiene buenos hábitos de programación, pero puede evitar problemas con algún estilo de codificación incorrecto, por ejemplo:
if ((a> b) == TRUE)
Esto podría ser un desastre si define manualmente VERDADERO como 1, mientras que el valor interno de VERDADERO es otro.
fuente
>
operador siempre produce 1 para verdadero, 0 para falso. No hay posibilidad de que ningún compilador de C se equivoque. Las comparaciones de igualdad conTRUE
yFALSE
son de mal estilo; lo anterior se escribe más claramente comoif (a > b)
. Pero la idea de que diferentes compiladores de C pueden tratar la verdad y lo falso de manera diferente es simplemente incorrecta.Por lo general, en el lenguaje de programación C, 1 se define como verdadero y 0 se define como falso. De ahí por qué ves lo siguiente con bastante frecuencia:
Sin embargo, cualquier número que no sea igual a 0 también se evaluaría como verdadero en una declaración condicional. Por lo tanto, usando lo siguiente:
Puede demostrar explícitamente que está tratando de ir a lo seguro haciendo falso igual a lo que no es cierto.
fuente