Точки последовательности. Является ли одна сторона присваивания последовательной перед другой в c ++?

Я понимаю, что это неопределенное поведение:

int i = 0;
int a[4];
a[i] = i++;  //<--- UB here

потому что порядок оценки i для левой стороны и правой стороны не определены ( ; единственная точка последовательности).

Делая это рассуждение шаг вперед, мне кажется, что это было бы не определено неуточненное поведение:

int i = 0;

int foo(){
return i++;
}

int main(){
int a[4];
a[i] = foo();
return 0;
}

Даже если есть несколько точек последовательности на правой стороне = насколько я понимаю, это все еще не определено не указано ли f() или же a[i] оценивается первым.

Верны ли мои предположения? Нужно ли проявлять кропотливую осторожность, когда я использую глобальную или статическую переменную в левой части назначения, которую правая рука ни при каких обстоятельствах не изменяет?

7

Решение

a[i] = foo();

Вот неопределенные будь то foo или же a[i] оценивается первым. В новой редакции C ++ 11 эти две оценки не являются последовательными. Это само по себе не вызывает неопределенного поведения, хотя. Это когда есть два неупорядоченных доступа к одному и тому же скалярному объекту, по крайней мере один из которых пишет, где он делает. Вот почему a[i] = i++; это UB.

Разница между этими двумя утверждениями заключается в том, что призыв к foo() действительно вводит точку последовательности. Формулировка C ++ 11 отличается: исполнение внутри называется функции неопределенно упорядочены относительно других оценок внутри призвание функция.

Это означает, что есть частичное упорядочение между a[i] а также i++ внутри foo, В результате либо a[0] или же a[1] будет установлен в 0, но программа хорошо определена.

6

Другие решения

a[i] = i++;

Это неопределенное поведение, потому что значение i одновременно изменяется и доступен между двумя точками последовательности (и доступ напрямую не участвует в вычислении следующего значения i).
Это также неопределенное поведение, потому что порядок эвлятации не определен (приращение i может произойти до или после использования i в качестве индекса в a).

Когда вы вводите вызов функции, например:

a[i] = foo();

вызов функции вводит две дополнительные точки последовательности: одну до ввода функции и одну после возврата функции.

Это означает, что приращение i Внутри функция окружена двумя точками последовательности и не вызывает неопределенного поведения.

Это все еще неопределенное поведение, хотя будет ли выполнен вызов функции перед использованием i в качестве указателя в левой части задания или после.

1

По вопросам рекламы [email protected]