Regla 0x1014h: Detector de operadores de incremento o decremento múltiples en una misma expresión
Estructuras de control y flujo (0x10XX)
0x1014h: Detector de operadores de incremento o decremento múltiples en una misma expresión¶
Enunciado normativo¶
NO DEBE modificarse la misma variable más de una vez mediante operadores de incremento o decremento (
++,--) dentro de una misma sentencia. Cada modificación DEBE escribirse como una sentencia separada.
¿Por qué existe esta regla?¶
El problema¶
El estándar deja sin especificar el orden de evaluación de una expresión
que modifica la misma variable dos veces. x = i++ + ++i puede dar resultados
distintos según el compilador, el nivel de optimización o la plataforma; incluso
puede no tener un resultado definido. Es comportamiento indefinido.
Aun cuando el resultado fuera estable, el lector no puede predecir el valor intermedio sin evaluar con cuidado cada efecto. Separar las modificaciones en sentencias elimina la ambigüedad y hace disponible el valor intermedio.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Comportamiento indefinido | El estándar no obliga a un resultado único (ISO §6.5). |
| Portabilidad | GCC, Clang y -O0/-O2 pueden diferir. |
| Depuración | El valor de la variable cambia dos veces en la misma línea. |
| Legibilidad | Hay que contar los efectos para saber el resultado. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §6.5 apartado 2 establece que, si un objeto se modifica más
de una vez entre dos puntos de secuencia, el comportamiento es indefinido.
§6.5.2.4 y §6.5.3.1 definen ++ y --. La cátedra prohíbe el patrón y exige
una modificación por sentencia; se relaciona con 0x2011h: Prohibición de asignaciones múltiples a una variable sin lectura intermedia (dead store) (dead store) y
0x3003h: No mezcles operaciones de asignación y comparación en una sola línea (no mezclar operaciones).
Alcance y excepciones¶
Prohibido modificar la misma variable con
++/--dos veces en una sentencia, o combinarla con otra modificación en el mismo punto de secuencia.Permitido:
i++como sentencia propia;for (i = 0; i < n; i++)porque cada modificación está en su propio punto de secuencia.Es un caso particular de una regla más general: no mezclar lectura y escritura de la misma variable sin un punto de secuencia intermedio.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — suma con dos incrementos¶
int i = 5;
int x = i++ + ++i;Por qué falla: i se modifica dos veces antes del punto de secuencia que marca
el ;. El valor de x es indefinido; el compilador podría dar 12, 13 u otro.
❌ Contraejemplo 2 — índice y elemento en la misma sentencia¶
indice = 0;
valores[indice] = indice++;Por qué falla: se escribe indice y se incrementa en la misma sentencia, sin
punto de secuencia intermedio. El resultado depende del orden de evaluación y no
es portable.
✅ Ejemplo conforme 1 — modificaciones separadas¶
int i = 5;
i++;
int x = i;
i++;Cada efecto tiene su sentencia y su punto de secuencia; el valor intermedio es observable y el resultado es determinista.
✅ Ejemplo conforme 2 — índice explícito¶
size_t indice = 0;
valores[indice] = 0;
indice++;Primero se usa el índice, después se avanza. El código funciona igual en cualquier compilador y se puede poner un punto de corte entre ambas líneas.
⚠️ Casos límite¶
i = i++;: doble modificación en la misma sentencia; indefinido.Llamadas con el mismo argumento:
f(i++, i++)también es indefinido por el orden indeterminado de evaluación de argumentos.Optimización: el comportamiento indefinido no se arregla con
-O0; el código debe reescribirse.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Regla 0x1014h: ++/-- múltiples. |
gcc | gcc -Wall -Wextra -Wsequence-point | warning: operation on 'i' may be undefined. |
clang | clang -Wall -Wextra | warning: multiple unsequenced modifications to 'i'. |
Checklist de autocontrol¶
¿Alguna sentencia modifica la misma variable con
++/--dos veces?¿Hay dos modificaciones de la misma variable sin punto de secuencia?
¿Separé cada incremento en su propia sentencia?
¿Compilé con
-Wsequence-point?
Reglas relacionadas¶
0x2011h: Prohibición de asignaciones múltiples a una variable sin lectura intermedia (dead store) — asignaciones múltiples sin lectura intermedia.
0x3003h: No mezcles operaciones de asignación y comparación en una sola línea — no mezclar asignación y comparación en una línea.
0x1003h: Utilizá el lazo for para iteraciones con rango o contador definido y while para lazos controlados por condiciones lógicas — el
formantiene el incremento en su propio punto de secuencia.