2013-01-21 2 views
5

Рассмотрим цикл в то время как ANSI C, чья единственная цель состоит в том, чтобы отложить исполнение:Может ли компилятор ANSI C удалить петлю задержки?

unsigned long counter = DELAY_COUNT; 
while(counter--); 

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

Мое чтение стандарта ANSI C состоит в том, что он может быть полностью удален соответствующим компилятором. Она не имеет ни один из побочных эффектов, описанных в 5.1.2.3:

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

... и этот раздел также говорит:

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

Означает ли это, что петля может быть оптимизирована? Даже если counter были volatile?

Примечания:

  1. То, что это не совсем так же, как Are compilers allowed to eliminate infinite loops?, потому что относится к бесконечных петель, и возникают вопросы о том, когда программа имеет право прекратить вообще. В этом случае программа, безусловно, продолжит эту линию в какой-то момент, оптимизирует или нет.
  2. Я знаю, что делает GCC (удаляет петлю для -O1 или выше, если counter не является volatile), но я хочу знать, что диктует стандарт.
+0

До тех пор, пока поведение * obserable * не изменяется, стандарт C не запрещает оптимизировать этот цикл. Таким образом, стандарт ничего не оговаривает. –

ответ

11

Соответствие стандарту C соответствует правилу «как есть», с помощью которого компилятор может сгенерировать любой код, который ведет себя «как если бы» выполнял ваши фактические инструкции на абстрактной машине. Так как не выполняющие какие-либо операции имеют одно и то же наблюдаемое поведение «как если бы» вы выполняли цикл, вполне допустимо не генерировать код для него.

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

Ситуация отличается для переменных volatile, поскольку доступ к неустойчивым считается как «наблюдаемый» эффект.

+0

@KingsIndian: Хе-хе, не беспокойтесь, я думаю, что среди ответы всегда хорошие :-) –

9

Означает ли это, что петля может быть оптимизирована?

Да.

Даже если счетчик нестабилен?

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

2

Если счетчик volatile, компилятор не может законно оптимизировать цикл задержки. В противном случае это возможно.

Циклы задержки, как это плохо, потому что время их записи зависит от того, как компилятор создает для них код. Используя разные варианты оптимизации, вы можете достичь разных задержек, чего вряд ли стоит от цикла задержки.

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

+2

Выполняете ли вы это на ассемблере или нет, в каком-то смысле не имеет значения. Циклы задержки, которые полагаются на определенное количество итераций, являются ошибочными - «задержка» изменяется в зависимости от ряда факторов, почти все из которых находятся вне контроля программиста. ** Не используйте такие петли задержки. ** –

+1

@NikBougalis Не обязательно верно. Если процессор является относительно немым и каждый раз выполняет команды с использованием того же количества часов (потому что он немой и не имеет кеширования), и если частота часов не изменяется, задержки будут довольно стабильными, если только прерывания включены, а ISR выполняются часто и занимают много времени. А во время аппаратной инициализации прерывания часто отключаются временно или до завершения инициализации. Если все эти условия выполнены, нет проблем с циклами задержки. –

+0

@NikBougalis Процессоры RISC на встроенных системах имеют счетные задержки большую часть времени, и петли задержки могут иметь свое время очень хорошо. –

1

Стандарт определяет поведение, которое вы видите. Если вы создаете дерево зависимостей для DELAY_COUNT, вы увидите, что оно имеет свойство изменения без использования, что означает, что его можно устранить. Это относится к неустойчивому случаю. В неустойчивом случае компилятор не может использовать дерево зависимостей для попытки удалить эту переменную и, как таковая, остается задержка (поскольку волатильность означает, что аппаратное обеспечение может изменить отображаемое значение памяти ИЛИ в некоторых случаях означает «мне действительно это нужно, не бросайте его прочь »). В случае, если вы смотрите на то, что он помечен как volatile, он сообщает компилятору, пожалуйста, не отбрасывайте его здесь по какой-то причине.

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

  • Нет связанных вопросов^_^