c++ c undefined-behavior

En C y C++, ¿una expresión que usa el operador de coma como “a=b,++ a;” no está definida?



undefined-behavior (2)

Toma estos tres fragmentos de código C:

1) a = b + a++ 2) a = b + a; a++ 3) a = b + a, a++

Todo el mundo sabe que el ejemplo 1 es una cosa muy mala e invoca claramente un comportamiento indefinido. El ejemplo 2 no tiene problemas. Mi pregunta es con respecto al ejemplo 3. ¿El operador de coma funciona como un punto y coma en este tipo de expresión? ¿2 y 3 son equivalentes o 3 es tan indefinido como 1?

Específicamente estaba considerando esto con respecto a algo como free(foo), foo = bar . Este es básicamente el mismo problema que el anterior. ¿Puedo estar seguro de que foo se libera antes de ser reasignado, o es un problema de secuencia clara?

Soy consciente de que ambos ejemplos son en gran medida inútiles y tiene mucho más sentido simplemente usar un punto y coma y terminar con él. Solo pregunto por curiosidad.


El caso 3 está bien definido.

La sección 6.5.17 de la norma C con respecto al operador de coma , dice lo siguiente:

2 El operando izquierdo de un operador de coma se evalúa como una expresión de vacío; hay un punto de secuencia entre su evaluación y la del operando correcto. Luego se evalúa el operando correcto; El resultado tiene su tipo y valor.

La sección 5.14 p1 del estándar C ++ 11 tiene un lenguaje similar:

Un par de expresiones separadas por una coma se evalúa de izquierda a derecha; La expresión de la izquierda es una expresión de valor descartado. Cada cálculo de valor y efecto secundario asociado con la expresión izquierda se secuencia antes de cada cálculo de valor y efecto secundario asociado con la expresión derecha. El tipo y el valor del resultado son el tipo y el valor del operando correcto; el resultado es de la misma categoría de valor que su operando derecho, y es un campo de bits si su operando derecho es un glvalue y un campo de bits.

Debido al punto de secuencia, a = b + a se garantiza que se evaluará completamente antes de a++ en la expresión a = b + a, a++ .

Con respecto a free(foo), foo = bar , esto también garantiza que foo se libere antes de asignar un nuevo valor.


a = b + a, a++; está bien definido, pero a = (b + a, a++); puede ser indefinido.

En primer lugar, la precedencia del operador hace que la expresión sea equivalente a (a = (b+a)), a++; , donde + tiene la prioridad más alta, seguido de = , seguido de,. El operador de coma incluye un punto de secuencia entre la evaluación de su operando izquierdo y derecho. Así que el código es, sin interés, completamente equivalente a:

a = b + a; a++;

Que por supuesto está bien definido.

Si hubiésemos escrito a = (b + a, a++); , entonces el punto de secuencia en el operador de coma no salvaría el día. Porque entonces la expresión habría sido equivalente a

(void)(b + a); a = a++;

  • En C y C ++ 14 o más, a = a++ tiene secuencia, (ver C11 6.5.16 / 3). Lo que significa que este es un comportamiento indefinido (Por C11 6.5 / 2). Tenga en cuenta que C ++ 11 y C ++ 14 estaban mal formulados y eran ambiguos.
  • En C ++ 17 o posterior, los operandos del operador = se secuencian de derecha a izquierda y esto todavía está bien definido.

Todo esto suponiendo que no se produzca una sobrecarga del operador C ++. En ese caso, se evaluarán los parámetros de la función de operador sobrecargado, se realizará un punto de secuencia antes de llamar a la función, y lo que suceda a partir de ahí dependerá de los aspectos internos de esa función.