Regla 0x010Ch: Auditor de identificadores reservados con doble guion bajo o guion bajo inicial
Nomenclatura e identificadores (0x01XX)
0x010Ch: Auditor de identificadores reservados con doble guion bajo o guion bajo inicial¶
Enunciado normativo¶
NO DEBE declararse ningún identificador que comience con doble guion bajo (
__) ni con un guion bajo seguido de mayúscula (_A). Esos nombres están reservados para la implementación y la biblioteca estándar.
¿Por qué existe esta regla?¶
El problema¶
La implementación —el compilador y la biblioteca estándar— necesita nombres
internos que nunca choquen con el código del usuario. Para lograrlo, el estándar
reserva formalmente un conjunto de identificadores. Un programa que usa __x o
_Buffer invade ese espacio: hoy compila porque la implementación no usó ese
nombre exacto, pero una actualización del compilador o un #include distinto
pueden declarar el mismo símbolo. Como el usuario no controla esas cabeceras,
el conflicto es impredecible.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Compilación | Redefinición de una macro o símbolo interno: error: conflicting types o redefinition. |
| Comportamiento indefinido | Usar un identificador reservado que la implementación ya usa invalida el comportamiento del programa. |
| Portabilidad | El nombre puede estar libre en GCC y ocupado en Clang o viceversa. |
| Mantenibilidad | Oculta el propósito del identificador y confunde al lector. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §7.1.3 (Reserved identifiers) establece que todos los
identificadores que empiezan con guion bajo y mayúscula o con doble guion bajo
están reservados para cualquier uso, y que los que empiezan con un guion bajo
están reservados al nivel de archivo. El prefijo __ es exactamente el que
usan las variables internas del compilador y de libc. La cátedra lo prohíbe
porque el estudiante no puede auditar qué nombres usa la implementación. La
regla coincide con 0x010Ah: Prohibición de identificadores con prefijos reservados para el compilador (__ o _[A-Z]); se mantienen ambas por trazabilidad histórica
del catálogo.
Alcance y excepciones¶
Aplica a variables, funciones, tipos, macros, etiquetas y cualquier otro
identificador del código del estudiante. No aplica a los nombres que ya
vienen dentro de las cabeceras estándar: ésos los elige la implementación. Las
guardas de inclusión tradicionales con __ son igualmente incorrectas y deben
reemplazarse por el nombre del módulo en mayúsculas (0x5003h: Utilizá guardas de inclusión en todos los archivos de cabecera).
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Doble guion bajo en variables¶
int __variable_privada = 0;
int memoria__reserva = 0;Por qué falla: __variable_privada empieza con __, siempre reservado; y
memoria__reserva lo contiene, lo que también cae bajo la reserva de doble
guion bajo. Aunque compilen hoy, la implementación puede usarlos mañana.
❌ Contraejemplo 2 — Guion bajo con mayúscula y en guardas¶
int _Buffer = 0;
#define _MAX_LEN 256Por qué falla: _Buffer y _MAX_LEN empiezan con guion bajo seguido de
mayúscula, reservado para cualquier uso. La macro además puede pisar un símbolo
interno de la biblioteca.
✅ Ejemplo conforme 1 — Nombres propios explícitos¶
int contador_local = 0;
static size_t capacidad_actual = 0;Por qué cumple: sin guiones bajos iniciales, los nombres describen su rol y el
static restringe el enlace del global conforme a 0x0106h: Las variables globales deben ser declaradas como static o usar prefijo g_.
✅ Ejemplo conforme 2 — Guarda de inclusión correcta¶
#ifndef LISTA_H
#define LISTA_H
/* ... contenido ... */
#endifPor qué cumple: la guarda usa el nombre del módulo en SCREAMING_SNAKE_CASE
conforme a 0x5003h: Utilizá guardas de inclusión en todos los archivos de cabecera, y evita el prefijo reservado que el preprocesador usa
para sus propios símbolos.
⚠️ Casos límite¶
__en el medio: también reservado; no sólo importa el prefijo inicial.Un solo
_al inicio: reservado al nivel de archivo; en variables locales es legal pero la cátedra igualmente lo desaconseja.Sufijo
_t: reservado por POSIX para tipos; usar sólo entypedefs propios y con criterio (0x3004h: Utilizá typedef para definir tipos de estructuras con el sufijo _t).Macros internas de la biblioteca: no se deben redefinir ni invocar.
Nombres de funciones como
_exit: pertenecen a la implementación; no se reutilizan.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Reporta identificadores que empiezan con __ o _ + mayúscula. |
gcc / clang | gcc -Wall -Wextra -Wpedantic -std=c11 -c archivo.c | Advierte sobre identificadores reservados en algunos casos. |
| Revisión manual | — | Buscar el patrón __ y _[A-Z] en declaraciones y #define. |
Checklist de autocontrol¶
Ningún identificador mío empieza con
__ni con_seguido de mayúscula.Las guardas de inclusión usan el nombre del módulo (0x5003h: Utilizá guardas de inclusión en todos los archivos de cabecera).
No redefiní símbolos de la biblioteca estándar.
Uso
staticog_para los globales (0x0106h: Las variables globales deben ser declaradas como static o usar prefijo g_).Distingo un
_inicial de archivo de un_local y lo evito igual.
Reglas relacionadas¶
0x010Ah: Prohibición de identificadores con prefijos reservados para el compilador (__ o _[A-Z]) — misma prohibición de prefijos reservados.
0x5003h: Utilizá guardas de inclusión en todos los archivos de cabecera — guardas de inclusión con nombres propios.
0x0106h: Las variables globales deben ser declaradas como static o usar prefijo g_ — restringir el alcance de las globales.
0x3004h: Utilizá typedef para definir tipos de estructuras con el sufijo _t — sufijo
_treservado para tipos.0x0108h: Prohibición de identificadores con caracteres no ASCII (acentos, ñ) — identificadores restringidos al conjunto ASCII.