после прочтения о точках последовательности я узнал, что i = ++ i
не определено.
Так как насчет этого кода:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // that should also be undefined right?
Скажем так если инициализация p и q зависит от некоторого (сложного) условия. И они могут указывать на один и тот же объект, как в предыдущем случае. Что случится? Если он не определен, какие инструменты мы можем использовать для обнаружения?
Редактировать: Если два указателя не должны указывать на один и тот же объект, можем ли мы использовать ограничение C99? Что означает «строгий»?
Да, это неопределенное поведение — у вас есть две модификации объекта без точки следования между ними. К сожалению, автоматическая проверка этого очень сложна - лучшее, что я могу придумать, это добавить assert(p != q)
прямо перед этим, что, по крайней мере, даст чистую ошибку времени выполнения, а не что-то еще хуже. Проверка этого во время компиляции в общем случае неразрешима.
Лучший инструмент, чтобы не обнаруживать, но в первую очередь избегать этого, — это использовать передовые методы программирования. Избегайте побочных эффектов и выполняйте не более одной записи за одно задание. В этом нет ничего плохого
*q += 1;
*p = *q;
Если не указано иное, порядок вычисления операндов отдельных операторов и подвыражений отдельных выражений, а также порядок, в котором имеют место побочные эффекты. , не указано. Между предыдущей и следующей точкой следования сохраненное значение скалярного объекта должно быть изменено не более одного раза при вычислении выражения. Кроме того, доступ к предыдущему значению должен осуществляться только для определения сохраняемого значения. Требования настоящего параграфа должны выполняться для каждого допустимого порядка подвыражений полного выражения; в противном случае поведение не определено.
[ 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 ]
В результате возникает неопределенное поведение:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // Bad Line
В «Плохой строке» скалярный объект «i» обновляется более одного раза во время вычисления выражения. Тот факт, что доступ к объекту «i» осуществляется косвенно, не меняет правила.
Выражение такое же, как i=++i. Единственный инструмент, который может обнаружить это, это ваша голова. В C с властью приходит ответственность.