Подтвердить что ты не робот

Является ли "* p = ++ (* q)" undefined, когда p и q указывают на один и тот же объект?

после прочтения о точках последовательности, я узнал, что i = ++i - undefined.

Итак, как насчет этого кода:

int i;
int *p = &i;
int *q = &i;
 *p = ++(*q);           // that should also be undefined right?

Скажем, если инициализация p и q зависит от некоторого (сложного) состояния. И они могут указывать на тот же объект, что и в предыдущем случае. Что случится? Если это undefined, какие инструменты мы можем использовать для обнаружения?

Изменить: Если два указателя не должны указывать на один и тот же объект, можем ли мы использовать C99? Это то, что означает "строгий"?

4b9b3361

Ответ 1

Да, это поведение undefined - у вас есть две модификации объекта без точки последовательности между ними. К сожалению, проверка этого автоматически очень сложна - я могу лучше всего добавить assert(p != q) прямо перед этим, что, по крайней мере, даст чистую ошибку во время выполнения, а не что-то еще хуже. Проверка этого во время компиляции неразрешима в общем случае.

Ответ 2

Лучший инструмент, который нельзя обнаружить, но во избежание этого в первую очередь следует использовать хорошую практику программирования. Избегайте побочных эффектов и делайте не более одной записи за каждое задание. Нет ничего плохого в

*q += 1;
*p = *q;

Ответ 3

Выражение такое же, как я = ++ i. Единственный инструмент, который может его обнаружить, - это ваша голова. В C с силой приходит ответственность.

Ответ 4

Глава 5 Выражения

Точка 4:

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

[ Example:
  i = v[i ++];           / / the behavior is undefined
  i = 7 , i++ , i ++;    / / i becomes 9
  i = ++ i + 1;          / / the behavior is undefined 
  i = i + 1;             / / the value of i is incremented
—end example ]

В результате это поведение undefined:

int i;
int *p = &i;
int *q = &i;
*p = ++(*q);   // Bad Line

В "Bad Line" скалярный объект "i" обновляется более одного раза во время оценки выражения. Просто потому, что косвенный доступ к объекту "i" не изменяет правило.

Ответ 5

Это хороший вопрос. Единственное, что вы выделили, это "точки последовательности", чтобы процитировать из этого сайт

почему вы не можете полагаться на такие выражения, как: a [i] = я ++; потому что не существует точки последовательности, указанной для операторов присваивания, приращения или индекса, вы не знаете, когда возникает эффект приращения на i.

И, кроме того, это выражение выше одинаково, поэтому поведение undefined, так как для инструментов для отслеживания этого значения нет нуля, обязательно там splint, чтобы назвать его в качестве примера, но это стандарт C, поэтому, возможно, есть скрытый параметр в инструменте, о котором я еще не слышал, возможно Gimpel PC Lint или Riverblade Visual lint может помочь вы, хотя я признаю, что в этом отношении ничего не говорится о отслеживании поведения undefined.

Кстати, компилятор GCC версии 4.3.3 имеет эту опцию -Wsequence-point как часть предупреждений о предупреждении.. это находится в моем блоке Slackware 13.0...

Он просто показывает, что этот код может выглядеть нормально невооруженным глазом и будет компилироваться просто отлично, но позже может вызвать головные боли, лучший способ сделать это - проверить код, который может выявить то, что компилятор не может выбрать это лучшее оружие выбора!