Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x1005h: Reemplazá las condiciones ambiguas basadas en la 'veracidad' (truthiness) del tipo de dato

Estructuras de control y flujo (0x10XX)

Universidad Nacional de Río Negro

0x1005h: Reemplazá las condiciones ambiguas basadas en la ‘veracidad’ (truthiness) del tipo de dato

Enunciado normativo

DEBEN escribirse comparaciones explícitas que reflejen el tipo del dato: un char se compara contra '\0', un puntero contra NULL, un bool contra true o false, y un entero contra 0. NO DEBE depender de la veracidad implícita de un valor numérico o de un puntero.

¿Por qué existe esta regla?

El problema

En C, cualquier escalar distinto de cero es verdadero: if (x) funciona igual para un int, un char y un puntero. Esa comodidad borra la distinción entre tres chequeos que significan cosas distintas. Cuando el lector ve if (ptr) debe adivinar si el autor quiso preguntar por “puntero no nulo” o por “contenido distinto de cero”.

La comparación explícita elimina la adivinanza. En el caso del char evita confundir el carácter '0' (cuyo valor es 48) con el carácter nulo '\0' (valor 0), y en el caso del strcmp evita invertir la condición.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug lógicoif (strcmp(a, b)) ejecuta la rama cuando las cadenas son distintas.
LegibilidadEl lector debe inferir la intención del tipo del dato.

Fundamento en el estándar y en la cátedra

ISO/IEC 9899:2011 §6.8.4.1 establece que la condición de un if compara contra cero; §6.3.1.2 fija las conversiones aritméticas usuales. La cátedra obliga a hacer explícita esa comparación para que el código no dependa de reglas implícitas. Es complementaria de 0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0 para punteros contra NULL y de 0x301Ah: Validador de uso idiomático de tipos booleanos estándar para el tipo bool estándar.

Alcance y excepciones

Ejemplos exhaustivos

❌ Contraejemplo 1 — int y char evaluados por veracidad

if (cantidad)
{
    procesar(cantidad);
}

if (caracter)
{
    analizar(caracter);
}

Por qué falla: cantidad debería compararse contra 0 y caracter contra '\0'. Si se pretendía detectar un carácter válido, el '0' (48) también pasa la condición, y el carácter nulo también, según lo que se quería.

❌ Contraejemplo 2 — resultado de strcmp usado como booleano

if (strcmp(nombre, "admin"))
{
    dar_acceso();
}

Por qué falla: strcmp devuelve 0 cuando las cadenas son iguales; entonces la rama se ejecuta cuando son diferentes, justo lo contrario de la intención.

✅ Ejemplo conforme 1 — comparaciones explícitas por tipo

if (cantidad != 0)
{
    procesar(cantidad);
}

if (caracter != '\0')
{
    analizar(caracter);
}

Cada comparación declara qué se mide y contra qué valor neutro; el lector no infiere nada.

✅ Ejemplo conforme 2 — strcmp explícito y bool coherente

if (strcmp(nombre, "admin") == 0)
{
    dar_acceso();
}

bool es_valido = puntaje >= APROBADO;
if (es_valido)
{
    promover();
}

El resultado de strcmp se compara contra 0 y la variable bool se usa directamente; la intención queda expuesta sin ambigüedad.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cRegla 0x1005h: condición implícita.
gccgcc -Wall -Wextra -Wsign-comparewarning: comparison of integer expressions of different signedness.
Revisión manualif (var) donde var no es bool.

Checklist de autocontrol

Reglas relacionadas

Antipatrón: Comparación booleana explícita redundante

Síntoma en el código del estudiante

Aparecen comparaciones contra true, false, 1 o 0 sobre variables que ya son booleanas, agregando ruido a la condición:

if (es_valido == true)
{
    avanzar();
}

Diagnóstico

Mecanismo del defecto

En C cualquier valor distinto de cero es verdadero y el cero es falso (ISO/IEC 9899:2011 §6.8.4.1). Comparar un bool contra true produce true == true o false == true, es decir, el mismo valor que la variable original. La comparación es una tautología que no agrega información.

Consecuencia observable

No hay error de ejecución; el código funciona igual. El costo es de lectura: el lector procesa dos comparaciones donde bastaba una y debe confirmar que es_valido == true no esconde una negación. Además, el patrón invita a confundir = con == en un contexto donde el error queda tapado.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §6.8.4.1 establece que la condición de un if compara contra cero, y §7.18 (<stdbool.h>) define true como 1 y false como 0. La comparación bool == true es, por lo tanto, siempre equivalente al valor de la variable. La cátedra prioriza la claridad y prefiere la forma directa.

Corrección idiomática

❌ Código con el antipatrón
if (es_valido == true)
{
    avanzar();
}

if (encontrado == false)
{
    seguir_buscando();
}
✅ Código refactorizado
if (es_valido)
{
    avanzar();
}

if (!encontrado)
{
    seguir_buscando();
}

La forma directa y la negación con ! expresan la misma condición sin la comparación redundante. Nota: esta ficha entra en tensión con 0x1005h: Reemplazá las condiciones ambiguas basadas en la ‘veracidad’ (truthiness) del tipo de dato; la cátedra admite ambas formas, pero exige coherencia dentro del mismo archivo.

Errores típicos al compilar o ejecutar

No compila con error. Con -Wall puede aparecer:
warning: comparison is always false due to limited range of data type
solo si se compara contra un valor imposible, no por la redundancia.

El bug real aparece cuando el autor escribe:
if (es_valido = false)   // asigna en lugar de comparar

Checklist de verificación

Reglas relacionadas

Antipatrón: Comparación lógica invertida con strcmp() en condicional

Síntoma en el código del estudiante

Se usa el resultado de strcmp directamente como booleano, sin compararlo contra 0:

if (strcmp(nombre, "admin"))
{
    dar_acceso();
}

Diagnóstico

Mecanismo del defecto

strcmp devuelve un entero negativo, 0 o positivo según el orden lexicográfico (ISO/IEC 9899:2011 §7.24.4.2). Devuelve 0 cuando las cadenas son iguales. Al usarlo directamente como condición, el cero se interpreta como falso y cualquier otro valor como verdadero: la rama se ejecuta cuando las cadenas son diferentes, justo al revés de lo que sugiere el nombre.

Consecuencia observable

La validación de credenciales, nombres o claves queda invertida: se concede acceso a cualquier texto que no coincida con el esperado y se lo niega al correcto. Es un bug grave de seguridad que compila sin advertencias y se manifiesta como lógica incomprensible.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §7.24.4.2 especifica el valor de retorno de strcmp. Debido a que 0 significa igualdad, la comparación explícita es obligatoria. La cátedra exige comparar contra 0 (regla 0x1005h) y distingue el chequeo de cadenas del de punteros y caracteres.

Corrección idiomática

❌ Código con el antipatrón
if (strcmp(nombre, "admin"))
{
    dar_acceso();
}
✅ Código refactorizado
if (strcmp(nombre, "admin") == 0)
{
    dar_acceso();
}

if (strcmp(nombre, "admin") != 0)
{
    denegar_acceso();
}

La comparación contra 0 hace explícito que 0 es igualdad y != 0 es desigualdad. El lector ya no tiene que recordar la convención de strcmp.

Errores típicos al compilar o ejecutar

No hay error de compilación ni advertencia por defecto.

En ejecución, la rama se ejecuta para cualquier nombre distinto de "admin":
dar_acceso() se llama con nombres incorrectos. Un atacante entra con
cualquier usuario mientras no se llame "admin".

Checklist de verificación

Reglas relacionadas

Antipatrón: Comparación entre tipos enteros con y sin signo en condición

Síntoma en el código del estudiante

Se compara un entero con signo contra uno sin signo (por ejemplo int contra size_t) sin controlar la conversión:

int i = -1;
size_t n = 10;
if (i < n)
{
    procesar(i);
}

Diagnóstico

Mecanismo del defecto

Cuando un operando con signo se compara contra uno sin signo de rango igual o mayor, el valor con signo se convierte implícitamente a sin signo (ISO/IEC 9899:2011 §6.3.1.8). -1 se convierte en el mayor valor del tipo size_t (SIZE_MAX), que es enorme. La comparación i < n resulta entonces falsa, al revés de lo esperado.

Consecuencia observable

El if no entra aunque i sea negativo y menor que n; o bien un lazo que recorre hacia atrás se desborda. También aparece al recorrer un arreglo con un índice int que se vuelve negativo: se convierte a un índice gigantesco y provoca un acceso fuera de rango.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §6.3.1.8 define las conversiones aritméticas usuales: si el tipo sin signo tiene rango mayor o igual, el operando con signo se convierte a sin signo. La cátedra exige tipos consistentes y size_t para índices (regla 0x3010h), evitando la conversión accidental (regla 0x1005h).

Corrección idiomática

❌ Código con el antipatrón
int i = -1;
size_t n = 10;
if (i < n)
{
    procesar(i);
}
✅ Código refactorizado
size_t i = 0;
size_t n = 10;
if (i < n)
{
    procesar(i);
}

Ambos operandos son del mismo tipo sin signo y la comparación es segura. Si el valor con signo debe conservarse, se valida primero: if (i >= 0 && (size_t)i < n).

Errores típicos al compilar o ejecutar

Con -Wsign-compare (incluida en -Wextra):
warning: comparison of integer expressions of different signedness:
'int' and 'size_t' {aka 'long unsigned int'} [-Wsign-compare]

En ejecución, i = -1 se convierte a 18446744073709551615 y la condición
es falsa. Con un índice negativo, el acceso desborda el arreglo.

Checklist de verificación

Reglas relacionadas