如下代码,为什么main会返回0,而不是1呢?
int main() {
const int a = 0xA5A5;
int *b = (int *)(&a);
*b = 333;
if (*b == a) {
return 1;
}
return 0;
}
如果a是const变量,不能变。但是我们通过a的地址改变了它的值呀。
我翻了《C++编程思想》还有好多论坛和博客,讲的都太罗嗦了。
- const关键字的初衷是什么?
- 替换宏定义
- 便于调试
- 安全检查
- 怎么实现?
我们知道程序生成的整个过程,预编译->编译->汇编->链接。
宏定义替换在预编译时期替换宏。其实,const常量也是相同的,只不过这个过程放在了编译阶段。
const常量是在编译阶段做替换的,编译程序会根据常量表把const变量替换成立即数。
如下代码,生成的汇编代码和第一部分的生成的汇编代码是一模一样的。
int main() {
const int a = 0xA5A5;
int *b = (int *)(&a);
*b = 333;
if (*b == 333) {
return 1;
}
return 0;
}
除了做替换之外,a还和其他变量一样分配了内存空间。
而这部分内存空间再怎么变,a早就在编译阶段替换成立即数了,所以是改变不了的。
有人问,那么这个const变量是存在什么地方呢?常量表在哪里?
常量表,是对编译程序而言的,它是编译程序的内存,而我们最后在结果程序中是看不到的,是没有这个概念的。const变量被分成了,汇编代码中的立即数(不能改变)和分配的对应一块内存。后者方便我们调试。
如果你用gdb调试第一块代码,就会发现在gdb中,运行到第5行时,a的值是333,但却没走第8行。理解上面的论述,也就知道为什么gdb在这会不靠谱了。
const object - an object whose type is const-qualified, or a non-mutable subobject of a const object. Such object cannot be modified: attempt to do so directly is a compile-time error, and attempt to do so indirectly (e.g., by modifying the const object through a reference or pointer to non-const type) results in undefined behavior.
来自cppreference 意思就是,通过引用或者指针来改const的值是不靠谱的,别这样做。
附汇编代码
.file "aa.cpp"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $42405, -12(%rbp)
leaq -12(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movl $333, (%rax)
movq -8(%rbp), %rax
movl (%rax), %eax
cmpl $333, %eax ##注意这里,是直接用333来比较
jne .L2
movl $1, %eax
jmp .L4
.L2:
movl $0, %eax
.L4:
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-4)"
.section .note.GNU-stack,"",@progbits