在这样的声明中说出
char var;
if( var == 'x');
我们是否在第一时间为'x'分配了任何内存?
如果是,那是什么(堆栈/数据)?
谢谢!
答案 0 :(得分:24)
值'x'可以作为比较指令的一部分直接存储在代码段中,或者可以存储在代码段中以立即加载到寄存器中,或者存储在数据段中用于间接加载或相比。这取决于编译器。
答案 1 :(得分:7)
几乎所有针对功能强大的架构(16位及以上)的编译器都会将“x”的常量放在CPU指令中进行比较:
cmp r0, #'x'
功能较少的体系结构倾向于将这些常量放在const内存中的表中,并将其加载以进行比较,或者直接从内存中进行比较。
答案 2 :(得分:4)
这是针对已安装的GCC副本所针对的任何体系结构回答此类问题的技术。使用-S
标志获取合适代码片段的汇编源文件。或者,使用-Wa,-al
获取一个程序集列表,显示汇编程序生成的实际字节数。例如,
int foo(char var) {
if (var == 'x')
return 42;
return 17;
}
在我的Windows PC上编译gcc -c -Wa,-al
以生成
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)
; 'x'
的ASCII码为十六进制120或十六进制为0x78。您可以在偏移量为8的.text段中看到0x78,它将作为CMPB指令的一部分存储。身体的其余部分实现从我的样本片段中选择返回值,如果比较为真,则利用SETE指令使AL
为1,否则为0。其余指令DECL
,ANDL
和ADDL
会生成17或42,具体取决于整个AL
寄存器中EAX
寄存器的初始值。是整数函数的返回值存储在此体系结构中的地方。
答案 3 :(得分:1)
char
或double
不被视为对象。它们只是值而不是指内存位置。这包括'x'
和3.14
等文字。
编译器存储这些值的方式和位置超出了标准的范围。它甚至不必直接存储它们。例如,像x * 8
这样的表达式可以转换为汇编代码,它将x的值向左移动三位。