ключевое слово volatile на языке C?

У меня вопрос о volatile на языке C.

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

А также некоторые говорят, что volatile означает, что значение может быть изменено вне этого кода.

Я не могу понять второе высказывание, значит, переменную volatile можно изменить вне этого кода? как? и эти двое говорят, что оба правы?


person Community    schedule 28.04.2011    source источник


Ответы (6)


Утверждение «значение может быть изменено вне этого кода» в основном означает, что другая программа или оборудование может обновить эту переменную. Это вполне возможно. Один из способов подумать об этом - связать эту концепцию с файлом, который совместно используется несколькими программами. Файл может быть открыт, записан и прочитан сразу многими программами. Когда вы читаете файл, вы хотите убедиться, что вы читаете последнее обновление, а не самое старое.

Возвращаясь к ключевому слову volatile, помещая volatile перед переменной, по сути, делает то же самое. Он гарантирует, что то, что вы читаете из переменной, не основано на оптимизации компилятора или старой копии переменной, которая была у вашей программы. Более того, ключевое слово volatile обеспечивает выборку переменной из памяти при каждом доступе. Следовательно, оба эти утверждения верны в отношении ключевого слова volatile.

person WindsurferOak    schedule 28.04.2011
comment
Я не понимаю, как аппаратно меняют переменную? Означает ли это, что аппаратному обеспечению не нужен какой-либо метод или код для изменения переменной? - person ; 28.04.2011
comment
@ratzip: Да. Переменная - это место в памяти, которое содержит значение, а память - это просто часть оборудования (например, микросхема RAM). Многие компьютерные системы (клавиатура, сеть, аудиовход и т. Д.) Настроены так, что внешнее оборудование может напрямую изменять определенные области памяти. - person e.James; 28.04.2011

C не обязательно для компьютеров. Например, если вы разрабатываете для Game Boy Advance, вы часто сталкиваетесь с участками памяти, которые изменяются оборудованием, поэтому вы можете не изменять переменную в своем коде, но она все равно будет изменена. . Вот что означает volatile.

Добавляя ключевое слово volatile, вы сообщаете компилятору, что «Значение, хранящееся в этой переменной (ячейка памяти), может измениться, если мой код ничего не сделает».

person aviraldg    schedule 28.04.2011
comment
Почему это часть стандарта C, а не расширение для этих реализаций - не существует подходящего способа получить адрес, указывающий на память, которая ведет себя подобным образом. - person Random832; 28.04.2011
comment
@Random: Потому что так оно и есть. В любом случае, почти каждая платформа в какой-то момент должна будет взаимодействовать с оборудованием. - person Oliver Charlesworth; 28.04.2011
comment
На некоторых встроенных платформах. Как и в GBA, у вас есть регистры с отображением памяти, поэтому вы точно знаете, что определенная область памяти будет вести себя таким образом. - person aviraldg; 28.04.2011
comment
@Random: Вы можете это объяснить? Вы не думаете, что можно указать подключенным устройствам использовать определенные области памяти в качестве буферов или куда передавать полученные сигналы? - person Andrew Lazarus; 28.04.2011
comment
@Random: Это просто неправильно. Многопоточное приложение может легко создавать код, в котором два потока асинхронно обращаются к одному и тому же участку памяти. - person e.James; 28.04.2011
comment
@Andrew Lazarus это невозможно в переносимой программе на C - стандарт не определяет никакого способа сделать это. @ e.James А стандарт C не обеспечивает многопоточность, так почему он должен предоставлять ключевые слова, которые необходимы / полезны только при использовании расширений? - person Random832; 28.04.2011
comment
@ Random832: Потому что это было необходимо машинам, использовавшимся при разработке стандарта C? (и UNIX нуждался в этом.) - person aviraldg; 28.04.2011
comment
@Random: Стандарт C также не определяет, как должны быть разрешены #includes. Это не значит, что они бесполезны. - person Oliver Charlesworth; 28.04.2011

Примите во внимание любое из следующего:

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

В каждой из этих ситуаций память может быть изменена за пределами текущего потока.

Обратите внимание, что «в любое время, когда значение переменной изменяется в регистре, это значение должно влиять на память» является правильным, но не очень ясным.

person Oliver Charlesworth    schedule 28.04.2011
comment
а также оба высказывания верны? - person ; 28.04.2011
comment
но volatile очень и очень редко используется для многопоточного кода. - person curiousguy; 27.10.2011
comment
volatile также полезен в случае данных, которые могут быть изменены асинхронным событием, например, при выполнении кода обработчика сигнала (т.е.код обработчика сигнала изменил переменную). - person vyudh; 09.04.2013
comment
В спецификации C нет требования, чтобы volatile имел семантику получения / выпуска или любую другую семантику, которая действительно полезна для многопоточного кода. Помните, что разные потоки могут работать с несовместимыми кешами на разных процессорах; нет необходимости, чтобы компилятор реализовал volatile, чтобы это учесть. Если вы не пишете код для конкретного компилятора и не знаете, какие расширения языка C компилятор реализует в отношении volatile, вам не следует использовать volatile для семантики потоковой передачи. - person Eric Lippert; 10.06.2014
comment
@EricLippert: Стандарт C также не требует, чтобы соответствующая реализация подходила для любых целей. Тот факт, что Стандарт не требует, чтобы соответствующая реализация что-то делала, никоим образом не означает, что качественные реализации, предназначенные для низкоуровневого программирования, не должны этого делать. К сожалению, для компиляторов модно рассматривать проблемы качества реализации как предлог для реализации некачественной семантики. - person supercat; 14.07.2018

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

person Community    schedule 28.04.2011

это относится, например, к многопоточным приложениям: значение переменной может быть изменено несколькими потоками и, следовательно, должно быть «синхронизировано» с памятью при каждом доступе (независимо от того, читать или записывать значение).

person Flinsch    schedule 28.04.2011
comment
volatile очень и очень редко используется для многопоточного кода. - person curiousguy; 27.10.2011

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

person user2212525    schedule 04.02.2014