Regla 0x301Ah: Validador de uso idiomático de tipos booleanos estándar
Memoria, punteros y tipos (0x30XX)
0x301Ah: Validador de uso idiomático de tipos booleanos estándar¶
Enunciado normativo¶
DEBE usarse el tipo estándar
boolcontrueyfalsede<stdbool.h>. NO DEBEN definirse redefiniciones manuales comotypedef int BOOL,#define TRUE 1o#define bool int.
¿Por qué existe esta regla?¶
El problema¶
Antes de C99, C no tenía un tipo booleano y muchos cursos definían
typedef int BOOL; con #define TRUE 1 y #define FALSE 0. Esa práctica
sobrevive por costumbre, pero tiene desventajas concretas: BOOL ocupa el
tamaño de un int, TRUE y FALSE no son constantes del lenguaje sino macros
que pueden redefinirse, y el valor 2 también es “verdadero” para cualquier
condición, lo que difumina el contrato.
C99/C11 incorporan _Bool y, con <stdbool.h>, las macros bool, true y
false. El tipo _Bool garantiza que cualquier valor distinto de cero se
normaliza a 1 al asignarse, de modo que una variable bool sólo puede valer
0 o 1. Eso hace que sizeof(bool) == 1 sea típico y que las comparaciones
sean predecibles.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Desperdicio | typedef int BOOL ocupa 4 bytes en lugar de 1. |
| Ambigüedad | TRUE puede redefinirse y 2 también compila como verdadero. |
| Incompatibilidad | Funciones de la biblioteca que usan bool no aceptan BOOL sin conversión. |
| Mantenibilidad | Cada archivo redefine sus propias constantes booleanas. |
Fundamento en el estándar y en la cátedra¶
C11 §6.2.5 introduce _Bool como tipo entero estándar; §7.18 define
<stdbool.h>, que declara bool como alias de _Bool y las macros true y
false. La cátedra prohíbe las redefiniciones manuales porque contradicen el
estándar y la convención de comparaciones explícitas de 0x1005h: Reemplazá las condiciones ambiguas basadas en la ‘veracidad’ (truthiness) del tipo de dato. Se
relaciona además con 0x0103h: Las constantes (const o #define) deben nombrarse en MAYUSCULAS_SNAKE_CASE para el nombre de las constantes.
Alcance y excepciones¶
Aplica a todo valor lógico: banderas, resultados de comparación almacenados,
retornos de predicado y parámetros de control. No prohíbe usar enteros cuando
el dominio no es lógico (contadores, índices, códigos). Tampoco obliga a comparar
un bool contra true/false en todos los casos: la condición directa
if (activo) es legible; lo que se prohíbe es depender de la “veracidad” de un
entero.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Redefinición manual del booleano¶
typedef int BOOL;
#define TRUE 1
#define FALSE 0
BOOL activo = TRUE;Por qué falla: BOOL ocupa el tamaño de un int y no restringe los valores.
activo = 5; es válido y deja la variable en un estado que ninguna función
espera. TRUE y FALSE son macros que pueden redefinirse accidentalmente en
otra cabecera.
❌ Contraejemplo 2 — Redefinir bool o comparar contra 1¶
#define bool int
bool activo = 1;
if (activo == 1)
{
ejecutar();
}Por qué falla: se redefine el nombre que <stdbool.h> provee, lo que provoca
conflictos si otra cabecera lo incluye. Además, comparar un valor lógico contra
1 en lugar de usar true es un caso de “veracidad implícita” que
0x1005h: Reemplazá las condiciones ambiguas basadas en la ‘veracidad’ (truthiness) del tipo de dato desaconseja: activo == 1 no es lo mismo que activo != 0 si el
valor pudiera ser otro distinto de cero.
✅ Ejemplo conforme 1 — Uso idiomático de <stdbool.h>¶
#include <stdbool.h>
bool activo = true;
if (activo)
{
ejecutar();
}bool es el tipo estándar, true y false son sus valores, y la condición
directa es clara. El compilador normaliza cualquier valor asignado a 0 o 1.
La función que devuelve bool puede comunicar éxito sin ambigüedad.
✅ Ejemplo conforme 2 — Predicado con retorno bool¶
#include <stdbool.h>
bool es_mayor_de_edad(int edad)
{
return edad >= 18;
}El retorno bool expresa el resultado lógico y se integra con la documentación
de 0x2007h: Los valores de retorno numéricos deben definirse como constantes de preprocesador o enums. El llamador puede escribir if (es_mayor_de_edad(edad)) y la
semántica es inequívoca.
⚠️ Casos límite¶
Campos de bits: un
boolen un campo de bits (bool activo : 1;) es válido en C11, aunque la combinación puede tener matices de implementación; documentalo.Interoperabilidad: una API que usa
intpara indicar éxito no debe convertirse aboola ciegas; adaptá el contrato en la frontera.sizeof(bool): suele ser 1, pero la norma no lo garantiza; si el tamaño importa, verificá consizeof.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | typedef de BOOL/bool manual o #define TRUE/FALSE. |
gcc / clang | gcc -Wall -Wextra -std=c11 ... | Redefiniciones de bool o macros que colisionan con <stdbool.h>. |
| Revisión manual | — | Comparaciones de banderas contra literales distintos de true/false. |
Checklist de autocontrol¶
¿Incluí
<stdbool.h>en lugar de definir mi booleano?¿Usé
bool,trueyfalseestándar?¿Evité
typedef int BOOLy#define TRUE?¿Comparé contra
true/falsecuando hace falta explicitar?¿Reservé los enteros para dominios que no son lógicos?
Reglas relacionadas¶
0x1005h: Reemplazá las condiciones ambiguas basadas en la ‘veracidad’ (truthiness) del tipo de dato — comparaciones explícitas acordes al tipo de dato.
0x0103h: Las constantes (const o #define) deben nombrarse en MAYUSCULAS_SNAKE_CASE — convención de mayúsculas para constantes simbólicas.
0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0 — el caso análogo para punteros y
NULL.