Почему компилятор не генерирует предупреждение или ошибку, если некоторые ограничительные указатели указывают на один и тот же объект?
Если у нас есть функция:
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
будет тот же объект. Но почему этот код может быть успешно скомпилирован?
4 ответа
restrict
в основном это обещание программиста компилятору, что указатель является единственным, который будет использоваться для доступа к объекту, на который он указывает (в пределах области действия указателя).
Компилятор (обычно) не проверяет это обещание - он оставляет эту ответственность за программистом. Если программист понимает это неправильно, наказанием будет неопределенное поведение.
Обычно обнаружение этого типа UB невозможно. Вызывающая функция могла уже получить указатели от другого модуля компиляции. Вот почему в целом это "просто" UB, потому что в качестве ограничения он не может быть обнаружен во время компиляции.
Ничто не мешает компилятору выдавать диагностику в таких случаях. Почему ваш разработчик компилятора не счел нужным внедрить такую диагностику, вам придется спросить прямо там.
Весь смысл restrict
это сказать компилятору, что он может предположить, что нет никакого перекрытия между памятью, на которую указывает ограниченный указатель, и любой другой памятью, доступной в этой точке, так что компилятор может сделать оптимизацию невозможной без такого предположения. Если бы компилятор сам мог сказать, что такого перекрытия нет, то в ключевом слове не было бы необходимости. Создание кода в func
быть ошибкой победит всю цель ключевого слова. Что касается вызова func
Так как компилятор не может в общем сказать, нарушено ли ограничение, нет необходимости отмечать случаи, когда он может это сказать. Некоторые высококачественные компиляторы с правильно установленными уровнями предупреждений могут выдавать предупреждение при таких обстоятельствах, как func
позвоните по вашему вопросу.
Этот код может успешно скомпилироваться, потому что в этом нет ничего плохого.
Проще говоря, это стандартный совместимый код. Стандарт требует диагностики только для плохо сформированного кода, а этот код - нет.
Это то же самое, что вам разрешено стрелять себе в голову, это не значит, что вы должны это делать, и если вы делаете только то, что вы не виноваты в том, что не мешали вам делать это.