【C++】 const补充
一、局部变量
笔记主要记录对const的一些深入理解,C语言中的const只是让变量变为只读属性,其本质还是变量,不是真正意义上的常量(只有enum枚举定义的才是常量).
注意:语法来讲const变量不能被直接赋值,但是由于const局部变量会存在栈里,可以通过指针来修改const变量.这种操作被称为未定义的行为,即不同的编译器可能结果不一样,所以不太建议修改这样操作。
C中const
#include <stdio.h>
int main()
{
const int c = 0; //const局部变量
int* p = (int*)&c;
*p = 5; //通过指针修改const变量
printf("c = %d *p = %d\n", c,*p); //c = 5 *p = 5
printf("&c = %p p = %p\n", &c,p); // &c = 000000000061FE14 p = 000000000061FE14
return 0;
}
- 在C中,const局部变量是在栈中,所以通过地址去修改可以修改,并且再次读取读的也是栈中修改后的数据。
C++中const
#include <stdio.h>
int main()
{
const int c = 0; //const局部变量
int* p = (int*)&c;
*p = 5; //通过指针修改const变量
printf("c = %d *p = %d\n", c,*p); //c = 0 *p = 5
printf("&c = %p p = %p\n", &c,p); //&c = 000000000061FE14 *p = 000000000061FE14
return 0;
}
- 在C++中,多了一个符号表,const变量在预处理时处理,编译器只对其值读取一次 。当遇到&符号时,会将其在栈中重新分配空间,p所修改的地址是分配空间的值,但是符号表中c的值并未改变,但是如果加上volatile关键字修饰,则每次使用都重新读取(打破只读取一次的限定),不让编译器优化,此时c的值就是修改后的值,此时就退化成C语言中的情况。
二、全局变量
C/C++ 全局const
#include <stdio.h>
const int c = 0; //const全局变量
int main()
{
int* p = (int*)&c;
*p = 5; //修改const变量 段错误
printf("c = %d\n", c);
return 0;
}
全局变量而言没有不同,因为const修饰的全局变量在编译后会存储在只读区域,如果使用指针修改的话只读区域的数据时会发生段错误。
三、const与define
上面提到C++中const会在预处理时处理,此时就容易想到和define功能类似。但是他两还有一定的区别。
- const常量: 由编译器处理,它会对const常量进行类型检查和作用域检查
- define宏定义: 由预处理器处理,直接进行文本替换,不会进行各种检查
作用域检查
#include <stdio.h>
void f()
{
#define a 3 //定义宏
const int b = 4; //定义局部变量
}
int main()
{
f();
printf("a=%d", a); //文本直接替换不进行作用域检查
//printf("b=%d",b); //b的作用域在f函数内
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!