Соответствующая часть из стандарта C:
6.3.2.2 void
(несуществующее) значение выражения void (выражение, имеющее тип void) никоим образом не должно использоваться, и неявные или явные преобразования (кроме void) не должны применяться к такому выражению. Если выражение любого другого типа оценивается как пустое выражение, его значение или обозначение отбрасывается. (Пустое выражение оценивается на предмет его побочных эффектов.)
Где побочные эффекты определены в 5.1.2.3/2:
Доступизменчивый объект, изменение объекта, изменение файла или вызов функции, которая выполняет любую из этих операций, - это все побочные эффекты , которые являются изменениями в состоянии среды выполнения.
Чтение энергонезависимой переменной не является побочным эффектом.
То есть, если доступ к x
является побочным эффектом, то код должен быть оценен (выполнен). Это только тот случай, когда x
равен volatile
. Так что (void)x;
не вызовет неопределенного поведения.
В противном случае было бы неопределенным поведение использовать локальную переменную x
, потому что ее адрес никогда не берется нигде внутри области действия.
В случае *p
у вас есть ясное lvalueдоступ к переменной с изменяемыми значениями через оператор *
, поэтому компилятор должен прочитать переменную. Независимо от актерского состава до (void)
.
Пример ниже также будет оценен, но вызывает неопределенное поведение (если не взят адрес самого указателя p
):
char* volatile p;
(void)p;