Я понимаю, что это неопределенное поведение:
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]
оценивается первым.
Верны ли мои предположения? Нужно ли проявлять кропотливую осторожность, когда я использую глобальную или статическую переменную в левой части назначения, которую правая рука ни при каких обстоятельствах не изменяет?
a[i] = foo();
Вот неопределенные будь то foo
или же a[i]
оценивается первым. В новой редакции C ++ 11 эти две оценки не являются последовательными. Это само по себе не вызывает неопределенного поведения, хотя. Это когда есть два неупорядоченных доступа к одному и тому же скалярному объекту, по крайней мере один из которых пишет, где он делает. Вот почему a[i] = i++;
это UB.
Разница между этими двумя утверждениями заключается в том, что призыв к foo()
действительно вводит точку последовательности. Формулировка C ++ 11 отличается: исполнение внутри называется функции неопределенно упорядочены относительно других оценок внутри призвание функция.
Это означает, что есть частичное упорядочение между a[i]
а также i++
внутри foo
, В результате либо a[0]
или же a[1]
будет установлен в 0, но программа хорошо определена.
a[i] = i++;
Это неопределенное поведение, потому что значение i
одновременно изменяется и доступен между двумя точками последовательности (и доступ напрямую не участвует в вычислении следующего значения i
).
Это также неопределенное поведение, потому что порядок эвлятации не определен (приращение i
может произойти до или после использования i
в качестве индекса в a
).
Когда вы вводите вызов функции, например:
a[i] = foo();
вызов функции вводит две дополнительные точки последовательности: одну до ввода функции и одну после возврата функции.
Это означает, что приращение i
Внутри функция окружена двумя точками последовательности и не вызывает неопределенного поведения.
Это все еще неопределенное поведение, хотя будет ли выполнен вызов функции перед использованием i
в качестве указателя в левой части задания или после.