Это неопределенное поведение - PullRequest
4 голосов
/ 03 марта 2020

Насколько я понимаю, эта программа должна иметь неопределенное поведение.

#include <stdio.h>

int main()
{
   int a = 3, b = 3, c = 10, d = 20;
   int e = (a++ * ++b)-((c / b) * a) + d;
   printf("%d", e)  ;

   return 0;
}

Стандарт C99 §6.5 ¶2 гласит:

Между предыдущей и следующей точкой последовательности объект должен иметь свое сохраненное значение, измененное не более одного раза с помощью вычисления выражения , Кроме того, предыдущее значение должно быть прочитано только для определения значения, которое будет сохранено.

Таким образом, в строке, определяющей 'e', a и b читаются не только для определения что хранить в a и b, но также для вычисления выражения ((c / b) * a)

Однако g cc не выдает предупреждение даже при -Wsequence-point warning.

Что мне здесь не хватает?

1 Ответ

3 голосов
/ 03 марта 2020

При компиляции с помощью компилятора clang (версия - clang-1001.0.46.4), получая эти предупреждения:

   p.c:6:19: warning: unsequenced modification and access to 'b' [-Wunsequenced]
       int e = (a++ * ++b)-((c / b) * a) + d;
                        ^        ~
   p.c:6:14: warning: unsequenced modification and access to 'a' [-Wunsequenced]
       int e = (a++ * ++b)-((c / b) * a) + d;
                ^                     ~

Из стандартов C11 # 6.5p2 [выделение добавлено]

2 Если побочный эффект скалярного объекта не секвенирован относительно , либо другой побочный эффект для того же скалярного объекта, либо вычисление значения с использованием значения того же скалярного объекта поведение не определено . Если существует несколько допустимых упорядочений подвыражений выражения, поведение не определено, если такой непоследовательный побочный эффект возникает в любом из порядков.84)

Выражение вызывает неопределенное поведение.


Редактировать:

Вопрос, помеченный gcc, поэтому для полноты ответа ниже приведен вывод при компиляции с gcc компилятором с опцией -Wall :

p.c:6:19: warning: operation on 'b' may be undefined [-Wsequence-point]
    int e = (a++ * ++b)-((c / b) * a) + d;
                   ^
p.c:6:14: warning: operation on 'a' may be undefined [-Wsequence-point]
    int e = (a++ * ++b)-((c / b) * a) + d;
              ^

Обратите внимание, что, если мы не указываем какие-либо параметры (например, -Wall или -Wsequence-point) для gcc во время компиляции, это не выдает никакого предупреждающего сообщения для рассматриваемого выражения, но это не в случае с clang компилятором.

...