2015-01-07 2 views
6

Рассмотрим этот пример кода:Когда можно полностью исключить изменчивую переменную?

int main(void) 
{ 
    volatile int a; 
    static volatile int b; 

    volatile int c; 
    c = 20; 
    static volatile int d; 
    d = 30; 

    volatile int e = 40; 
    static volatile int f = 50; 

    return 0; 
} 

Без volatile компилятор может оптимизировать на все переменные, так как они никогда не будут читаться.

Я думаю, что a и b можно оптимизировать, так как они полностью не используются, см. unused volatile variable.

Я думаю, что c и d не могут быть удалены с момента их написания, и записи на изменчивые переменные должны действительно произойти. e должен быть эквивалентен c.

GCC не оптимизирует f, но также не дает инструкции для его написания. 50 задается в разделе данных. LLVM (clang) полностью удаляет f.

Являются ли эти утверждения истинными?

  1. Изменчивую переменную можно оптимизировать, если она никогда не доступна.
  2. Инициализация статической или глобальной переменной не считается доступом.
+0

Возможный дубликат [Почему волатильность необходима в c?] (Http://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c) – Gopi

+0

Я думаю, что этот вопрос более конкретен в отношении того, как изменчивые переменные могут быть оптимизированы. –

+0

был 'c = 30;' предназначен для чтения 'd = 30;'? –

ответ

8

Записывает изменчивые переменные (даже автоматические) в качестве наблюдаемого поведения.

С11 (N1570) 5.1.2.3/6:

Наименее требований по соответствующей реализации является:

- Доступы к летучим объектам оценивается строго в соответствии с правилами абстрактной машины ,

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

- Динамика входа и выхода интерактивных устройств должна иметь место, как указано в 7.21.3. Цель этих требований состоит в том, чтобы как можно скорее появлялись небуферизованные или строковые буферизированные выходные данные , чтобы убедиться, что сообщения запроса действительно отображаются до программы, ожидающей ввода.

Это Наблюдаемое поведение программы.

Возникает вопрос: действительно инициализации (e, f) рассчитывать как "доступ"? Как указывал Сандер де Дайкер, 6.7.3 говорит:

Что представляет собой доступ к объекту, который имеет нестабильный тип, определяется реализацией.

что означает, что до компилятора, могут ли быть оптимизирован прочь e и f - но это должно быть документально!

+2

6.7.3 гласит: «Что представляет собой доступ к объекту, который имеет изменчивый тип, определяется реализацией», который касается вашего последнего абзаца. –

4

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

От могучего Standard (курсив мой):

(C11, 6.7.3p7) «Объект, который имеет летучий квалифицированное тип может быть изменен таким образом, неизвестных в реализации или у других неизвестных побочные эффекты. Поэтому любое выражение, обратное , к такому объекту должно оцениваться строго в соответствии с правилами абстрактной машины, , как описано в 5.1.2.3. "

После этого даже простая инициализация переменной следует рассматривать как доступ. Помните, что спецификатор static также инициирует инициализацию объекта (до 0) и, таким образом, получает доступ.

Теперь, как известно, компиляторы ведут себя по-разному с изменчивым квалификатором, и я думаю, что многие из них просто оптимизируют большинство изменчивых объектов вашей примерной программы, кроме тех, которые имеют явное назначение (=).

+1

Обратите внимание, что объявления не являются выражениями –

+1

, но он говорит немного далее: «Что представляет собой доступ к объекту, который имеет тип с изменчивой квалификацией, определяется реализацией». что объясняет упомянутую разницу в поведении между gcc и llvm. –

+0

Если волатильная автоматическая переменная не имеет своего адреса, это предполагает, что компилятор мог бы оптимизировать все инструкции, которые могли бы получить к нему доступ в тех же ситуациях, где это могло бы быть сделано для энергонезависимой переменной *, но * она не могла двигаться побочный эффект, который возникает после такого доступа к точке, находящейся перед ней, и наоборот. – supercat

Смежные вопросы