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

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

int IE6_Bugs = 12345;
int Win_Bugs = 56789;

Да - все очищается. IE6_Bugs имеет 123 456 сохраненных в, он - определенный адрес памяти.

Тогда что относительно..

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

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

Но:

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

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

15
задан lamas 30 January 2010 в 13:47
поделиться

6 ответов

Ваш второй метод вызывается, если найдено точное совпадение, он используется перед парамами.

Из MSDN :

При выполнении разрешения перегрузки метод с массивом параметров может быть применим либо в обычной, либо в расширенной форме (раздел 7,4,2,1). Расширенная форма метода доступна, только если обычная форма метода неприменима и только если метод с той же подписью, что и расширенная форма, еще не объявлен в том же типе.

Их пример:

using System;
class Test
{
   static void F(params object[] a) {
      Console.WriteLine("F(object[])");
   }
   static void F() {
      Console.WriteLine("F()");
   }
   static void F(object a0, object a1) {
      Console.WriteLine("F(object,object)");
   }
   static void Main() {
      F();
      F(1);
      F(1, 2);
      F(1, 2, 3);
      F(1, 2, 3, 4);
   }
}

Вывод:

F();
F(object[]);
F(object,object);
F(object[]);
F(object[]);
-121--4690817-

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

-121--716353-

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

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

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

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

18
ответ дан 1 December 2019 в 01:23
поделиться

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

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

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

8
ответ дан 1 December 2019 в 01:23
поделиться

DirectInput устарел по уважительным причинам. Как я знаю, он создает дополнительный поток и просто запрашивает интерфейс Windows ' Raw Input . Для лучшей производительности я бы использовал Raw Input напрямую.

Если производительность не является проблемой для вас (и я думаю, что это так для 2D игры на текущем оборудовании), следуйте рекомендациям Microsoft и используйте оконные сообщения, как описано Джоном Кноеллером.

-121--2465974-

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

-121--2599546-

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

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

4
ответ дан 1 December 2019 в 01:23
поделиться

Способ сказать, что проверка сгенерированного кода ассемблера или выпуская через него в отладчик. Различные компиляторы могут сделать это по-разному. Он также может зависеть от вариантов ваших компиляторов, таких как «Отладка».

Комментарии здесь о постоянном складе и устранении теста «если» будут применяться, если бы заявления были префиксированы «Const».

0
ответ дан 1 December 2019 в 01:23
поделиться

Ваш второй метод вызывается, если найдено точное совпадение, он используется перед парамами.

Из MSDN :

При выполнении разрешения перегрузки метод с массивом параметров может быть применим либо в обычной, либо в расширенной форме (раздел 7,4,2,1). Расширенная форма метода доступна, только если обычная форма метода неприменима и только если метод с той же подписью, что и расширенная форма, еще не объявлен в том же типе.

Их пример:

using System;
class Test
{
   static void F(params object[] a) {
      Console.WriteLine("F(object[])");
   }
   static void F() {
      Console.WriteLine("F()");
   }
   static void F(object a0, object a1) {
      Console.WriteLine("F(object,object)");
   }
   static void Main() {
      F();
      F(1);
      F(1, 2);
      F(1, 2, 3);
      F(1, 2, 3, 4);
   }
}

Output:

F();
F(object[]);
F(object,object);
F(object[]);
F(object[]);
-121--4690817-

boost:: variant отображает свои типы через type , который является списком MPL. Можно выполнять операции по спискам MPL, используя mpl:: для _ каждый :

struct printer {
    template<class T> void operator()(T t) {
        std::cout << typeid(T).name() << std::endl;
    }
};

// ... 
typedef boost::variant<int, char> var;
boost::mpl::for_each<var::types>(printer());
-121--2814179-

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

4
ответ дан 1 December 2019 в 01:23
поделиться

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

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

2
ответ дан 1 December 2019 в 01:23
поделиться