Где литералы хранятся в таком выражении, если (var == 'x')? - PullRequest
5 голосов
/ 15 сентября 2010

Скажите в таком утверждении

char var;

if( var == 'x');

Выделяем ли мы какую-либо память для 'x' на первом месте?

Если да, что это (стек / данные)?

Спасибо!

Ответы [ 4 ]

24 голосов
/ 15 сентября 2010

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

7 голосов
/ 15 сентября 2010

Почти каждый компилятор, нацеленный на работоспособную архитектуру (16-разрядную и более), помещает константу 'x' в инструкцию процессора для сравнения:

cmp  r0, #'x'

Менее способные архитектуры, как правило, помещают такие константы в таблицу в постоянной памяти и либо загружают ее для сравнения, либо выполняют сравнение непосредственно из памяти.

4 голосов
/ 15 сентября 2010

Вот методика, позволяющая ответить на некоторые вопросы, подобные этим, для любой архитектуры, для которой установлена ​​установленная копия GCC. Используйте флаг -S, чтобы получить исходный файл сборки для подходящего фрагмента кода. В качестве альтернативы используйте -Wa,-al, чтобы получить список сборок, показывающий фактические байты, сгенерированные ассемблером. Например,

int foo(char var) {
    if (var == 'x')
        return 42;
    return 17;
}

компилируется с gcc -c -Wa,-al на моем ПК с Windows для создания

GAS LISTING C:\DOCUME~1\Ross\LOCALS~1\Temp/ccyDNLLe.s                   page 1


   1                            .file   "q3715034.c"
   2                            .text
   3                            .p2align 4,,15
   4                    .globl _foo
   5                            .def    _foo;   .scl    2;      .type   32;
.endef
   6                    _foo:
   7 0000 55                    pushl   %ebp
   8 0001 31C0                  xorl    %eax, %eax
   9 0003 89E5                  movl    %esp, %ebp
  10 0005 807D0878              cmpb    $120, 8(%ebp)
  11 0009 5D                    popl    %ebp
  12 000a 0F94C0                sete    %al
  13 000d 48                    decl    %eax
  14 000e 83E0E7                andl    $-25, %eax
  15 0011 83C02A                addl    $42, %eax
  16 0014 C3909090              ret
  16      90909090
  16      90909090

Линии 7 и 9 - это все, что осталось от котельной пластины входа функции, а линии 11 и 16 - котельная плита выхода функции. Строка 8 очищает весь регистр возвращаемого значения до 0. Строка 10 - это фактическое сравнение var == 'x', и вы можете увидеть магическое число $120 в инструкции cmpb $120, 8(%ebp); код ASCII для 'x' равен 120 десятичному или 0x78 в шестнадцатеричном виде. Вы можете увидеть 0x78 в сегменте .text со смещением 8, где он хранится как часть инструкции CMPB. В остальной части тела реализован выбор возвращаемых значений из моего образца фрагмента, используя инструкцию SETE, чтобы сделать AL равным 1, если сравнение было истинным, или 0 в противном случае. Остальные инструкции DECL, ANDL и ADDL затем генерируют 17 или 42 в зависимости от начального значения регистра AL во всем регистре EAX, в котором хранятся возвращаемые значения из целочисленных функций. в этой архитектуре.

1 голос
/ 15 сентября 2010

Энтони ответил на практическую сторону вещей. Позвольте мне прокомментировать вопрос с более теоретической точки зрения языка. Стандарт C ++ определяет литералы как rvalue выражений , за исключением строковых литералов, которые lvalue выражений относятся к массивам. Стандарт C ++ имеет четкое представление о том, что такое объект . По сути, объект является чем-то типа типа (int, double, MyClass, ...), который имеет адрес . Но чистые значения r из скалярных типов , таких как char или double, не считаются объектами. Они просто значения и не относятся к области памяти. Это включает в себя литералы, такие как 'x' и 3.14.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...