const常量的不同形式、数组和指针

const常量的不同形式

const关键字出现在不少编程语言中,它是防御性描述,提醒编译器注意相应的变量或常量不能被修改。当然,编译器无法检测hack刻意躲过检查的行为。

不同语言的const

  • C/ObjC语言的const修饰的不是常规的”常量”,而是”不可修改”的变量。但实际上,和常量效果一样。本质在于C语言根本没有所谓常量的概念,用const来假装有常量。

  • C++ const真的是常量,比C语言的使用更广泛,尤其是类成员函数用到const引用,iostream就包含很多const修饰符。C++17引入了constexpr关键字,可修饰新的类型,如函数、类等,使得常量控制更强大。
    • constexpr int get_size() { return 3; }
    • char arr[get_size()]; // 合法!
    • 尽管如此,constexpr不一定保证编译期完成,C++20又引入了consteval确保一定是编译期完成。

  • Java用final代表常量,有意思的是const属于Java的预留关键字,但不能用。

  • C#除了有const,受局限于声明时就必须初始化。readonly变量可以推迟到构造函数初始化。

  • Python没有const关键字,按照约定常量用大写字母,实际上语法上没有限定不能被修改,可能源于Python设计对常量的期待很低。

  • Go支持单个或多个标识符的const初始化,多个标识符初始化需要用括号包起来。

  • Rust支持const常量,属于编译期常量,let虽然也代表常量,属于运行期常量,加mut代表运行期变量.

  • JS在ES6之后引入了const关键字代表常量,let声明的变量属于变量。var属于deprecated的函数内变量。

  • Swift/仓颉 没有const关键字, 用let代表常量,var代表变量。

  • VB用Const代表常量。

const的指针还是常量?

有指针的编程语言就是复杂,const和指针的组合让大家摸不到头脑。究竟是变量是const还是指针const?一个比较有意思的原则是,”从右向左读”的解析方法很实用。

  • C语言:”const int * const p”解读方式是”从右向左”读的方法
    • const int * p是”p” “指向” “整形” “常量”.
    • const int * const p是”p” “常” “指向” “整形” “常量”.

const和代码大小

一般而言相比没有const修饰,加const修饰后不会增加代码大小,可能减小代码大小。编译器利用const修饰优化对应的变量,如果可能用常数代替或者引用已有变量而不拷贝新的变量。

数组和指针

虽然有单独的文章描述数组和指针,但二者的关系实在值得再写一篇文章。

编译器的视角

  • 常常看到书籍上这么写"C/C++数组的本质是指针",这没有问题。编译器看到数组名,也就是数组首地址,即数组第一个元素的指针。对于超过二维的X维数组,概念更多,不仅是第一个元素指针,也是X-1维数组的指针。

  • 数组的sizeof: 数组int arr[10]占用空间sizeof(arr)不是sizeof(int *), 因为编译器知道arr的大小,此时当做原始数组。
    • 对于VLA可变数组,编译器很聪明地根据外部传入的数组元素个数乘以每个元素大小, 例如int类型数组,rax寄存器是数组元素个数,左移2位指令 shl $0x2,%rax 获得整个数组大小。

  • 用extern指针形式引用数组:
    • 定义了数组变量int a[10], 外部文件引用它不能用extern int *a, 否则此处的a代表a[0], 而非数组a地址,这不是本意。不论是VS2019还是GCC, 都是这个结果。
    • 可以用extern int arr[]引用外部数组,这样才会符合预期。


若文章对您有帮助,欢迎关注。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是程序员小迷(致力于C、C++、Java、Kotlin、Android、iOS、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值