2013-05-18 5 views
0

Если мы имеем функцию:Почему компилятор не генерирует предупреждение или ошибку, если некоторые ограничивающие указатели указывают на один и тот же объект?

void func(int *restrict a, int *restrict b, int *restrict c) { 
    *c = *a + *b; 
} 

В принципе, этот код может привести к некоторой погрешности:

int aa = 1; 
func(&aa, &aa, &aa); 

, потому что в func, *a*b*c будет тот же объект. Но почему этот код можно скомпилировать успешно?

ответ

0

Этот код может быть скомпилирован успешно, потому что в нем нет ничего плохого.
Проще говоря, это стандартный совместимый код. Стандарт требует диагностики только для плохо сформированного кода, а этот код - нет.

Это то же самое, что и вам разрешено стрелять в голову, это не значит, что вы должны, и если вы делаете, то только вы должны обвинять других не в том, чтобы не мешать вам это делать.

+1

Возможно, что «ничего плохого» вы подразумеваете «никаких нарушений ограничений». Это все еще неопределенное поведение. То же самое относится и к нарушению constness объекта, который также не является нарушением ограничения. – Sebivor

+0

@undefinedbehaviour: Точно, существует различие между кодом, имеющим нарушение ограничений и неопределенным/неуказанным/реализацией, прежний требует, чтобы последняя версия компилятора не выполняла. –

+1

Это не совсем так. См. Пример в 5.1.1.3p2. – Sebivor

4

restrict - это в основном обещание программиста компилятору, что указатель является единственным, который будет использоваться для доступа к объекту, на который он указывает (в пределах области действия указателя).

Компилятор не выполняет (вообще) проверку этого обещания - он оставляет эту ответственность программисту. Если программист ошибается, неопределенное поведение будет наказанием.

1

Целью restrict является рассказать компилятору, что он может предположить, что между памятью, на которую указывает ограниченный указатель, и любой другой доступной в данный момент памяти, нет перекрытия между ними, чтобы компилятор мог делать оптимизации без таких предположение. Если компилятор может сказать, что такого перекрытия не существует сам по себе, тогда не будет необходимости в ключевом слове. При создании кода в func ошибка приведет к поражению всей цели ключевого слова. Что касается вызова func: так как компилятор не может вообще сказать, нарушено ли ограничение, нет необходимости отмечать случаи, когда он может сказать. Некоторые высококачественные компиляторы с установленными надлежащим уровнем предупреждения могут выдать предупреждение в таких обстоятельствах, как звонок func в ваш вопрос.

2

Как правило, обнаружение этого типа UB невозможно. Вызывающая функция уже могла получить указатели от другого модуля компиляции. Вот почему, в общем, это «просто» UB, потому что в качестве ограничения он не может быть обнаружен во время компиляции.

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