Usando valores booleanos en C

Resuelto neuromancer asked hace 15 años • 19 respuestas

C no tiene ningún tipo booleano incorporado. ¿Cuál es la mejor manera de usarlos en C?

neuromancer avatar Dec 17 '09 19:12 neuromancer
Aceptado

De mejor a peor:

Opción 1 (C99 y más reciente)

#include <stdbool.h>

opcion 2

typedef enum { false, true } bool;

Opción 3

typedef int bool;
enum { false, true };

Opción 4

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

Explicación

  • La opción 1 funcionará sólo si usa C99 (o más reciente) y es la "forma estándar" de hacerlo. Elija esto si es posible.
  • Las opciones 2, 3 y 4 tendrán en la práctica el mismo comportamiento idéntico. #2 y #3 no usan #defines, lo cual en mi opinión es mejor.

Si estás indeciso, ¡elige el número 1!

Andreas Bonini avatar Dec 17 '2009 12:12 Andreas Bonini

Algunas reflexiones sobre los valores booleanos en C:

Tengo la edad suficiente para usar ints simples como mi tipo booleano sin definiciones de tipo ni definiciones o enumeraciones especiales para valores verdadero/falso. Si sigue mi sugerencia a continuación de no comparar nunca con constantes booleanas, entonces solo necesitará usar 0/1 para inicializar las banderas de todos modos. Sin embargo, tal enfoque puede considerarse demasiado reaccionario en estos tiempos modernos. En ese caso, definitivamente se debería utilizar <stdbool.h>ya que al menos tiene el beneficio de estar estandarizado.

Como se llamen las constantes booleanas, úselas sólo para la inicialización. Nunca escribas algo como

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

Estos siempre pueden ser reemplazados por los más claros.

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

Tenga en cuenta que, en realidad, estos pueden leerse en voz alta de manera razonable y comprensible.

Dé nombres positivos a sus variables booleanas, es decir, fullen lugar de notfull. Esto último conduce a un código difícil de leer fácilmente. Comparar

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

con

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

Los dos primeros leen con naturalidad, aunque !notfulles incómodo de leer tal como está y se vuelve mucho peor en expresiones booleanas más complejas.

En general, se deben evitar los argumentos booleanos. Considere una función definida así

void foo(bool option) { ... }

Dentro del cuerpo de la función, está muy claro lo que significa el argumento, ya que tiene un nombre conveniente y, con suerte, significativo. Pero los sitios de llamadas parecen

foo(TRUE);
foo(FALSE):

Aquí, es esencialmente imposible saber qué significa el parámetro sin mirar siempre la definición o declaración de la función, y empeora mucho si agrega aún más parámetros booleanos. Yo sugiero cualquiera de los dos

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

o

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

En cualquier caso, el sitio de la llamada ahora parece

foo(OPT_ON);
foo(OPT_OFF);

que el lector tiene al menos la posibilidad de comprender sin tener que desenterrar la definición de foo.

Dale Hagglund avatar Dec 18 '2009 04:12 Dale Hagglund

Un booleano en C es un número entero: cero para falso y distinto de cero para verdadero.

Consulte también Tipo de datos booleanos , sección C, C++, Objective-C, AWK .

Fortega avatar Dec 17 '2009 12:12 Fortega

Aquí está la versión que usé:

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

Porque falso solo tiene un valor, pero un verdadero lógico podría tener muchos valores, pero la técnica establece que verdadero es lo que el compilador usará para lo opuesto a falso.

Esto soluciona el problema de que alguien codifique algo que se reduciría a esto:

if (true == !false)

Creo que todos estaríamos de acuerdo en que no es una buena práctica, pero por el costo único de hacer "verdadero =! Falso" eliminamos ese problema.

[EDITAR] Al final usé:

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

para evitar colisiones de nombres con otros esquemas que estaban definiendo truey false. Pero el concepto sigue siendo el mismo.

[EDITAR] Para mostrar la conversión de un número entero a booleano:

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

¡El primero (más a la derecha)! convierte el número entero distinto de cero en 0, luego el segundo (más a la izquierda) ! convierte el 0 en un myfalsevalor. Dejaré como ejercicio para el lector la conversión de un número entero cero.

[EDITAR] Mi estilo es utilizar la configuración explícita de un valor en una enumeración cuando se requiere el valor específico, incluso si el valor predeterminado fuera el mismo. Ejemplo: debido a que falso debe ser cero, lo uso false = 0,en lugar defalse,

[EDITAR] Muestre cómo limitar el tamaño de enumeración al compilar con gcc:

typedef __attribute__((__packed__)) enum { myfalse = 0, mytrue = !myfalse } mybool;

Es decir, si alguien hace:

struct mystruct {
    mybool somebool1;
    mybool somebool2;
    mybool somebool3;
    mybool somebool4;
}

el tamaño de la estructura será de 4 bytes en lugar de 16 bytes.

Be Kind To New Users avatar May 14 '2014 22:05 Be Kind To New Users

Si está utilizando un compilador C99, tiene soporte integrado para tipos bool:

#include <stdbool.h>
int main()
{
  bool b = false;
  b = true;
}

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

Gary Willoughby avatar Dec 17 '2009 14:12 Gary Willoughby