Rust/zig 等现代语言里面都引入了不可变语法,很方便。那么,如果我用C语言时,也想要某个变量或 struct field 保持不变,该怎么做呢?我知道有 const 、宏替换(可能不可取)。除此之外,还有什么哪些办法?敬请各位道友赐教,谢谢。
另,如果能讲讲 const 的本质就更好了。
Rust/zig 等现代语言里面都引入了不可变语法,很方便。那么,如果我用C语言时,也想要某个变量或 struct field 保持不变,该怎么做呢?我知道有 const 、宏替换(可能不可取)。除此之外,还有什么哪些办法?敬请各位道友赐教,谢谢。
另,如果能讲讲 const 的本质就更好了。
下述代码是我之前的笔记,仅供参考。
#include <stdio.h>
// const int a = 10; // 全局const变量,编译器会将其放在text段,其值不能更改,否则会Segmentation fault
int main()
{
const int a = 10; // 函数中的const变量在栈上,其值可以更改
int* b = (int*)&a;
*b = 20;
printf("a:%d\n",a);
return 0;
}
结论:我认为const关键字仅起到提醒作用,提醒你不要改变这个变量的值。const修饰变量的值到底能不能变,需要看变量所处位置[当然,根本原因在于编译器]。
嗯。这么说,const 不能保证值不变。谢谢。
Rust 的不可变应该是为了计算生命周期吧,感觉面向过程的语言,有没有不可变没有那么重要。
已初始化的全局变量在程序镜像的data段而不是text段吧
格式化字符串会放到rodata,但我没见过初始化了的全局变量放text的
和编译器有关,有的编译器会
什么编译器会,能举个例子吗
好久不搞 c 语言了,具体哪些忘记了。把全局常量放到 text 段的编译器挺多的,应该能查查
为什么没说呢,elf spec说了.text里是放可执行指令的,全局变量不算可执行指令吧
这个要说怎么看了,我记得最早的时候是不太区分 .text
.rodata
.rodata1
.dynsym
等段的,统一都叫做 TEXT 段或 CODE 段,和 DATA 段做区分,具体的区分开数据和指令或其他符号是后来弄的,所以一些编译器产生的目标文件在 .text 段中直接包含了除了指令之外的其他数据和符号。 const 数据放到 .text 段中是因为在一些嵌入式环境中,.text 段的数据是提供只读保护的其他段的数据保证不了。
但也有例外有些比较老的编译器有把只读数据或字面值放到 .data 段的,这样的话就有可能能修改字面值,比如把 3 改成 4…
ELF 又不会给每次运行之前给你反汇编了研究到底是指令还是数据,只要是不会被执行到的位置塞什么都可以。
像 ARM 这样汇编器是会把常量放 text segment 最后面的。