const的小把戏。
const修饰不同的变量,会存放在不同的段,会得到不同的结果。
结论:const修饰初始化全局变量,数据存放在rodata段,不可被修改。
const修饰未初始化全局变量,数据存放在bss段,可用指针修改。
const修饰局部变量,数据存放在stack段,可用指针修改。
const修饰指向堆的指针,数据存放在heap段,可以用指针修改。
论证方法:
# include <stdio.h> # include <stdlib.h> const int a = 10; int main(void) { int *p = &a; *p = 20; printf("%d\n", a); return 0; }
结果:编译警告,执行段错误。
objdump -t a.o
可以看到,cosnt int a在rodata段
# include <stdio.h> # include <stdlib.h> const int a; int main(void) { int *p = &a; *p = 20; printf("%d\n", a); return 0; }
执行结果:编译警告,运行正常,输出20
可以看出,a只是一个COMMON符号,不属于任何段。再用objdump看下a.out
可以看出,a在bss段
# include <stdio.h> # include <stdlib.h> int main(void) { const int a = 10; int *p = &a; *p = 20; printf("%d\n", a); return 0; }
运行结果:编译警告,执行正常,输出20
未找到a,说明a不在rodata段中,也不再bss段中。gdb看下栈帧
由此可看出,a存在栈上。
# include <stdio.h> # include <stdlib.h> int main(void) { const int *a = malloc(sizeof(int)); int *p = a; *p = 20; printf("%d\n", *a); return 0; }
运行结果:编译警告,执行正常,输出20
objdump未找到a,说明a不在rodata段,不在bss段。gdb看一眼。
发现,a和p指向同一块地址,这款地址在堆中。