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 0x3019h: Prohibición de comparar punteros contra constantes numéricas distintas de NULL o cero

Memoria, punteros y tipos (0x30XX)

Universidad Nacional de Río Negro

0x3019h: Prohibición de comparar punteros contra constantes numéricas distintas de NULL o cero

Enunciado normativo

NO DEBE compararse un puntero contra literales numéricos mayores que cero (ptr == 1, ptr > 0, ptr == 0x1000). La única comparación numérica permitida es contra la constante de puntero nulo: NULL (o 0 como constante nula, según 0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0).

¿Por qué existe esta regla?

El problema

Un puntero es una dirección de memoria, no un número con el que se razona aritméticamente. En C, comparar un puntero contra un entero distinto de cero es una restricción que el compilador debe diagnosticar; si se fuerza con un cast, el resultado es definido por la implementación y no portable.

El problema pedagógico es más profundo: if (ptr > 0) sugiere que las direcciones “positivas” indican validez y que existe un orden entre punteros. No es así. Las únicas relaciones definidas entre punteros son igualdad y, dentro del mismo objeto arreglo, orden relativo (C11 §6.5.8). Fuera de ese contexto, > es comportamiento indefinido.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
No portabilidadLa comparación depende de la representación de direcciones.
Comportamiento indefinidoComparar con > punteros de objetos distintos (C11 §6.5.8).
Confusión de conceptoSe trata la dirección como un número mágico en lugar de un recurso.
MantenibilidadEl significado del literal no está definido en ninguna parte.

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

C11 §6.3.2.3 define que un entero constante con valor 0, o tal constante convertida a void *, es una constante de puntero nulo. Cualquier otro entero no es una constante de puntero nulo válida. C11 §6.5.8 sólo define las comparaciones relacionales entre punteros al mismo objeto arreglo. La cátedra exige que todo puntero se compare contra NULL, en coherencia con 0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0.

Alcance y excepciones

Aplica a todos los tipos de puntero, incluidos punteros a función. No prohíbe comparar punteros entre sí dentro del mismo arreglo para delimitar subrangos, ni comparar contra NULL. Tampoco regula los valores enteros que se guardan en un uintptr_t para diagnóstico: allí la conversión es explícita y su uso no es una comparación de punteros.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Comparación contra 1

if (ptr == 1)
{
    printf("Valido\n");
}

Por qué falla: 1 no es una constante de puntero nulo; es un entero. La comparación es una restricción y, si se fuerza con un cast a (int *)1, el compilador debe producir una dirección con ese valor, práctica no portable. El código sugiere que la dirección 1 tiene un significado especial, pero ese significado no está definido.

❌ Contraejemplo 2 — Ordenamiento de punteros no relacionados

if (ptr > 0)
{
    procesar(ptr);
}

Por qué falla: ptr > 0 compara el puntero contra el entero cero; además, la relación > entre un puntero y un entero no está definida por el estándar. La intención real —“el puntero es válido”— se expresa con ptr != NULL, que es portable y semánticamente correcto.

✅ Ejemplo conforme 1 — Comparación contra NULL

if (ptr != NULL)
{
    procesar(ptr);
}

NULL es la constante de puntero nulo: la comparación es válida y expresa la idea de validez. Es la forma que exige 0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0 y la que el compilador entiende sin conversiones.

✅ Ejemplo conforme 2 — Orden dentro del mismo arreglo

int *inicio = valores;
int *fin = valores + cantidad;
for (int *p = inicio; p < fin; p++)
{
    procesar(*p);
}

La comparación < es válida porque inicio y fin apuntan al mismo objeto arreglo. El orden relativo está definido por C11 §6.5.8 y el recorrido es portable. No hay literales mágicos ni comparaciones contra enteros.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cPuntero comparado contra literal distinto de NULL/0.
gcc / clanggcc -Wall -Wextra -std=c11 ...comparison between pointer and integer o ordered comparison of pointer with integer.
cppcheckcppcheck --enable=all archivo.ccomparePointers con literal.

Checklist de autocontrol

Reglas relacionadas