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

Должен ли использоваться неиспользованный изменчивый параметр?

Если я вызываю функцию с параметром volatile, и этот параметр не используется, должен ли компилятор создать параметр?

void consume( volatile int ) { }

...

consume( some_expr );

GCC выполняет это почетное, но я не уверен, что эта формулировка неустойчивой в стандартах требует этого. На мой взгляд, GCC делает правильные вещи - это логически назначение переменной volatile и поэтому не следует опускать (согласно 1.9-8 стандарта С++)

ПРИМЕЧАНИЕ. Целью этого является предотвращение удаления оптимизатором кода. То есть, он заставляет some_expr оцениваться. Он позволяет оптимизировать выражение, но гарантирует его выполнение.

Я добавляю C и С++ как теги, так как ответ на меня интересует меня, если есть какие-то различия. Я не думаю, что будет.

ANSWER. Я выбрал первый, так как считаю, что это правильная практическая реализация стандарта. Однако философская точка зрения Стива очень интересна и может на самом деле означать, что стандарт неоднозначен.

4b9b3361

Ответ 1

Неименованный аргумент consume не может быть прочитан, так как он не указан. Однако он инициализируется и инициализация (с помощью some_expr) является видимым побочным эффектом. Поэтому компилятор не может оптимизировать инициализацию.

Требуется ли это для фактической оценки some_expr другое дело. В общем, это не видимый побочный эффект, но может быть, если some_expr содержит под-выражения volatile.

[править] Обратите внимание, что "неназванная" часть может встречаться в двух местах. Вызывающий вообще не имеет возможности узнать, присвоен ли параметр (не говоря уже об использовании).

void consume( volatile int x);
consume( some_expr );
// other .cpp
void consume( volatile int ) { } // Same function.

Ответ 2

Можно утверждать об обратном, но я думаю, что реализация может опускать обращения к автоматическим объектам volatile при условии, что они в противном случае не имеют никакого отношения к программе, и при условии, что она либо запрещает программисту наблюдать за стеком (через немаркированные или только для чтения страницы, отладчики и т.д.) или, по крайней мере, предупреждает, что это не всегда будет иметь ожидаемый эффект. Необязательный параметр соответствует этому описанию.

Причина в том, что правило "как есть" говорит о видимых побочных эффектах и ​​говорит, что волатильные обращения являются видимыми побочными эффектами. Но если сама программа никоим образом не зависит от них, то стандарт не говорит о том, что объект фактически должен быть расположен "в стеке". Стандарт позволяет ему находиться в специальном месте памяти, предоставляемом аппаратным обеспечением, которое не может быть прочитано каким-либо образом, только для записи и записи на него не оказывает физического воздействия на аппаратное обеспечение. Поскольку это разрешено, кажется абсурдным говорить, что "требуется по стандарту", ​​что эта запись без эффекта на самом деле идет вперед. Как бы кто-нибудь знал? В стандарте не предусмотрено, что в бинарнике должны быть инструкции для выполнения записи, он предусматривает, что волшебный, нечитаемый секретный объект должен принимать определенное значение. Если я утверждаю, что это имеет значение, вы не можете доказать, что я ошибаюсь: -)

Невозможно написать соответствующую программу, которая полагается на такой волатильный доступ, который действительно возникает, или определить, была ли оценена оценка some_expr. Действительно это между вами и вашим отладчиком было ли оно вычислено или нет. Я видел, что отладчики ошибаются меньше.

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