Что делает C (++) со значениями, которые не хранятся в переменных?

Мне немного любопытно, как C и С++ обрабатывают данные, которые не хранятся в переменных, например:

int IE6_Bugs = 12345;
int Win_Bugs = 56789;

Да, все ясно. IE6_Bugs имеет 123456, сохраненный в нем определенный адрес памяти.

Тогда как насчет..

if ( IE6_Bugs + Win_Bugs > 10000 )
{
  // ...

Итак, C захватывает значения двух переменных и добавляет их, чтобы сравнить результат с int справа.

Но:

  • Достигает ли IE6_Bugs+Win_Bugs RAM? Или процессор напрямую сравнивает значения через свой собственный кеш?

  • Или в процессе компиляции приведенный выше оператор if преобразуется в нечто более понятное для машины? (Возможно, сначала просчитайте IE6_Bugs+Win_Bugs и сохраните его в некоторой переменной,...)

Ответы

Ответ 1

Он будет помещен в регистр в CPU (при условии, что он доступен). Регистр - это своего рода супербыстрая сверхмалая оперативная память, встроенная в процессор и используемая для хранения результатов промежуточных операций.

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

Имейте в виду, что независимо от того, является ли это выражением или числом, (x + y vs 10), его все равно нужно будет поместить в регистр, чтобы CPU мог получить к нему доступ и выполнить операцию, основанную на ее значение.

Для получения дополнительной информации ознакомьтесь с компьютерной архитектурой.

Ответ 2

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

Оптимизация, известная как "постоянная сворачивание", вычисляет значения постоянных выражений во время компиляции. В вашем конкретном примере интеллектуальный компилятор распознает, что ваше условие всегда будет истинным и не будет генерировать код для теста, поэтому значения 12345, 56789 и 10000 могут вообще не отображаться в машинный код, сгенерированный для вашей программы.

У вашего компилятора, вероятно, есть возможность сохранить промежуточный язык ассемблера, сгенерированный для вашей программы, например, g++ -S. Узнайте немного о своей архитектуре процессора и ассемблере, чтобы научиться понимать и даже полезно выводить из этого вывода.

Ответ 3

Хорошо, хороший компилятор будет делать постоянное распространение и сворачивание, поэтому в этом примере он заменит IE6_Bugs 12345 и Win_Bugs на 56789, а затем преобразует их в 69134. Тогда он, вероятно, также сбросит 69134 > 10000 на ' true "и полностью удалить ветвь во время компиляции.

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

Ответ 4

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

Ответ 5

Нет абсолютно никакого способа окончательно ответить на этот вопрос. Другие ответы здесь точны для большинства архитектур, но это не указано ни в одном из стандартов C/С++, которые являются аппаратно-агностическими.

Порядок оценки определяется стандартом. То, как вещи в конечном итоге обрабатываются в памяти, - это не так.

Ответ 6

Можно сказать, что нужно проверить сгенерированный код ассемблера или выполнить его в отладчике. Различные компиляторы могут делать это по-разному. Это также может зависеть от ваших параметров компилятора, таких как "DEBUG".

Замечания о постоянной сгибании и исключении теста "if" будут применяться, если объявления были префиксны "const".