假设我对全局命名空间(或任何其他命名空间)中的静态对象或基元有静态引用:
int a = 2;
int& b = a;
int main(int argc, char** argv) {
b++;
return b;
}
这是一个非常基本的例子,但编译器通常使用这段代码做什么?生成的机器代码是否实际遍历读/写a
的指针,或者编译器是否只插入a
的地址代替b
?
答案 0 :(得分:2)
对此的答案显然是编译器特定的。我决定尝试使用x86-64上的clang-500.2.79和-O3标志。如上所述,您的来源产生:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
movl _a(%rip), %eax
incl %eax
movl %eax, _a(%rip)
popq %rbp
ret
.cfi_endproc
.section __DATA,__data
.globl _a ## @a
.align 2
_a:
.long 2 ## 0x2
.section __DATA,__const
.globl _b ## @b
.align 3
_b:
.quad _a
正如您所看到的,a
和b
符号都被保留(分为_a
和_b
);这是必需的,因为这些符号具有全局联系。
如果您稍微更改代码,要将a
和b
声明为静态,结果会大不相同:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
movl $3, %eax
popq %rbp
ret
.cfi_endproc
在这种情况下,编译器能够完全优化a
和b
,并且只需要main返回常量3,因为其他编译单元无法使用这些值。< / p>
答案 1 :(得分:0)
我试图取消代码,
int pranit = 2;
int& sumit = pranit;
int main(int argc, char** argv) {
sumit++;
return sumit;
}
以下说明建议pranit有sumit的地址。
013B13C8 8B15 04803B01 MOV EDX,DWORD PTR [sumit] ; ConsoleA.pranit
此外,两个变量都有不同的地址,
Names in ConsoleA, item 313
Address=013B8004
Section=.data
Type=Library
Name=sumit
Names in ConsoleA, item 257
Address=013B8000
Section=.data
Type=Library
Name=pranit
我使用OllyDbg作为反汇编程序。