2013-03-08 2 views
1

Я не могу представить, что делает компилятор, когда, например, нет значения lvalue, например: number >> 1; Моя интуиция подсказывает мне, что компилятор будет отбрасывать эту строку из компиляции из-за оптимизации, и если оптимизация будет удалена, что произойдет? Использует ли регистр для манипуляции? или он ведет себя так, как если бы это был вызов функции, поэтому параметры передавались в стек, а используемая память помечена как освобожденная? ИЛИ он преобразует это в операцию NOP? Могу ли я увидеть, что происходит с помощью отладчика VS ++? Благодарим вас за помощь.C фиктивные операции

+7

Почему бы вам просто не взглянуть на сгенерированную сборку? Я уверен, что компилятор просто исключит выражение. Здесь нет стандартного ответа, компилятор может делать все, что захочет, пока семантика вашей программы не изменится. –

+1

Фактически, * если * 'number' является' volatile', компилятор ** должен тщательно протачивать и не может просто исключить выражение - чтение переменной volatile может иметь побочные эффекты. –

+0

Nik, Можете ли вы рассказать мне, почему компилятор не должен отбрасывать чтение из изменчивого, когда инструкция, содержащая чтение, не имеет никакого побочного эффекта? Я не вижу ничего, что поддерживало бы ваше утверждение в стандарте. Есть ли какое-то предложение, на которое вы ссылаетесь? – MikeB

ответ

1

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

Вы можете увидеть код, который компилятор испускает, используя параметр командной строки /FAsc компилятора Microsoft. Этот параметр создает файл списка, который выводит код объекта компилятору, перемежающийся с соответствующим исходным кодом.

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

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

+0

Спасибо за помощь :). Я сделал несколько экспериментов с этим на VS ++ с оптимизацией и без нее. Они дают тот же результат, когда никакая lvalue не дается ничего не делается. Нет инструкции даже для инициализации (число = 0) !!! Но что-то интересное случается так, как сказал Ник, когда это приводит к появлению некоторых других инструкций на «Разборке», начиная с шага инициализации волатильного номера int и инструкции бит-сдвига. Думаю, мне нужно глубже понять, что означает летучий. Спасибо вам за помощь. –

0

Предполагая, что number является обычной переменной целочисленного типа (не volatile), тогда любой компетентный оптимизирующий компилятор (Microsoft, Intel, GNU, IBM и т. Д.) Генерирует абсолютно НИЧЕГО. Не nop, никакие регистры не используются и т. Д.

Если оптимизация отключена (в «сборке отладки»), тогда компилятор может «делать то, что вы просили», потому что он не понимает, что это не происходит У меня есть побочные эффекты от кода. В этом случае значение будет загружено в регистр, сдвинутый вправо один раз. Результат этого не сохраняется нигде. Компилятор выполнит «бесполезное устранение кода» в качестве одного из шагов оптимизации - я не уверен, какой из них, но для такого рода относительно простой вещи, я ожидаю, что компилятор будет разбираться с довольно базовыми настройками оптимизации. В некоторых случаях, когда речь идет о циклах и т. Д., Компилятор не может оптимизировать код, пока не будут включены более продвинутые параметры оптимизации.

Как уже упоминалось в комментариях, если переменная является энергозависимой, то считывание памяти, записанное number, должно быть выполнено, поскольку компилятор ДОЛЖЕН читать volatile.

В Visual Studio, если вы «просмотрите разборку», он должен показать вам код, сгенерированный компилятором.

Наконец, если это был C++, существует также вероятность того, что переменная не является обычным целым типом, функция вызывает operator>>, когда этот код просматривается компилятором - эта функция может иметь побочные эффекты, кроме возвращения результат, поэтому вполне может быть выполнено. Но этого не может быть в C, так как нет перегрузки оператора.

+0

Спасибо за помощь :). Я сделал несколько экспериментов с этим на VS ++ с оптимизацией и без нее. Они дают тот же результат, когда никакая lvalue не дается ничего не делается !!! 00FB101C rep stos dword ptr es: [edi] \t int number = 0, result = 0; 00FB101E mov dword ptr [число], 0 00FB1025 mov dword ptr [результат], 0 номер << 1; } 00FB102C xor eax, eax –

+0

Так что это оптимизация, даже если у вас нет оптимизации. Это не совсем неожиданно. –

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