C/C++的const常量总结(c++语言const)
liuian 2025-07-07 20:09 65 浏览
“ 所谓常量,就是在代码运行过程中值恒定不变的标识符,该标识符的值可以是一个常数,也可以是字符串。”
在C/C++中,通常使用define宏定义或者const来定义常量,比如:
#define PI 3.1415926
const int a = 5;接下来我们来总结const常量的相关用法与注意事项。
01
为什么使用常量?
1. 使用常量可增加程序的可读性。
程序员应该都有这种经历:看别人的代码时为代码中某个数字而纠结,不知道这个数字表示什么意义,甚至自己写的代码,过一段时间再回头看,有可能都不记得代码里某个数字代表什么意思。比如计算一天包含的秒数,如果按照下式计算,虽然没错,但很可能会让人懵逼。24代表什么?两个60又分别代表什么?
int s = 24*60*60;比较推荐的做法是类似这样的,这样看起来就比较清晰了:
const int oneday_hour = 24;
const int onehour_minute = 60;
const int oneminute_second = 60;
const int oneday_second = oneday_hour * onehour_minute * oneminute_second;2. 使用常量可减少出错的概率。
程序员写代码时,经常需要在多个地方使用同一个数字或者同一个字符串,如果都是直接输入数字或者字符串,万一某个地方写错了,造成该处与其它地方的数字或字符串不一致,很可能导致严重bug。
比如以下代码,多个地方要用到Π值3.1415926,如果把3.1415926定义为一个常量,使用起来就方便多了,也不容易出错:
//不好的使用示例
double a = sin(3.1415926*5);
double b = cos(3.1415926*10);
double b = sin(3.1415926*100)*cos(3.1415926/2);
//推荐的使用示例
const double PI = 3.1415926;
double a = sin(PI*5);
double b = cos(PI*10);
double b = sin(PI*100)*cos(PI/2);3. 使用常量可以减少代码维护的工作量。
使用常量的情况下,程序员维护代码时如果要修改代码中某个数值,他只需要修改常量的值,那么代码中多处用到该常量的地方也就自己改了过来,而不需要程序员去一个地方一个地方地修改。
比如以下代码,计算b、c、d都要要到5.0这个数值,如果哪一天需求改变,需要把5.0改为20.0,在不好的示例中需要修改三行代码,在我们推荐的示例中只需要修改一行代码——把常量a的值改为20.0即可:
//不好的使用示例
float b = 5.0*3;
float c = 5.0 + 10;
float d = exp(5.0);
//推荐的使用示例
const float a = 5.0;
float b = a*3;
float c = a + 10;
float d = exp(a);4. 使用常量可提升程序的健壮性
编写代码时,我们经常希望某一个变量的值不被意外改变,或者某指针指向的对象不被意外改变,又或者某指针指向的对象的值不被意外改变(这里可能有点懵逼,读者暂时不用纠结,下文我们再详说)。然而在代码的汪洋大海中,难免会有意外发生,我们能做的就是使用常量来减小这种意外发生的概率。
比如以下函数,指针p作为输入参数,在该函数内部我们不希望p由其原本指向的地址被改为指向别的地址,同时希望指针p指向地址的值是可以改变的,那么可以使用const来修饰p,这样p指向的地址就不会被意外改变啦~
void func(int *const p)
{
int a = 3;
p = &a; //这样的操作是无效的,因为指针p被const修饰,其指向的地址不能被改变
*p = a; //这样的操作是有效的,p指向地址的值会被修改为a的值
}02
const常量与define常量的区别
在C/C++中,有const和define两种定义常量的方式,不过const常量相比define常量有更多的优点:
1. const常量有数据类型,define宏定义常量没有,编译器会对const常量可以进行数据类型的安全检查,但是对于define宏定义,编译器只是将其进行字符替换,这样的字符替换很容易出错。比如以下代码,如果使用不加括号的宏定义,将不能正确计算(a+b)/5.0,而是变成计算a+(b/5.0)了。
//define宏定义的做法
#define a 2.0
#define b 9.0
#define c1 a+b //不好的定义方法
#define c2 ((a)+(b)) //推荐的定义方法
void func1(void)
{
float d1 = c1/5.0; //本意是想计算(a+b)/5.0,但字符替换使计算变成了a+b/5.0
float d2 = c2/5.0; //正确计算了((a)+(b))/5.0 = (a+b)/5.0
}
//推荐的const常量的做法
const float a = 2.0;
const float b = 9.0;
const float c = a + b;
void func2(void)
{
float d = c/5.0; //正确计算了(a+b)/5.0
}
2. 有一些调试工具可以对const常量进行调试,但却无法调试define宏定义常量。
因此,我们还是建议尽量使用const常量。
03
建议的const常量定义规则
1. const常量应在.c或.cpp文件中定义,尽量不要在头文件中定义,因为假如头文件被多个.c或.cpp文件包含,那么定义于头文件中的常量将被多次重复定义,很可能造成严重错误。比如以下代码:
推荐的做法,在.c或.cpp文件中定义:
const int x = 15;不建议的做法,在头文件中定义:
#ifndef _TEST_H_
#define _TEST_H_
const int x = 15;
#endif虽然不建议在头文件中定义常量,但是对于全局常量,也就是我们不仅希望该常量能在其定义的.c或.cpp文件中使用,还可以在别的.c或.cpp文件中使用,那么可以在头文件中对其进行extern声明,这样一来只要别的.c或.cpp文件include了该头文件,它也就可以使用该常量了,比如以下代码:
#ifndef _TEST_H_
#define _TEST_H_
extern const int x;
#endif2. 如果一个常量与别的常量有联系,在定义的时候尽量把它们的联系包含进去:
//不推荐的做法
const int a = 5;
const int b = 5*100;
const int c = 5 + 5*100 - 64;
//建议的做法,在定义时把a、b、c的联系包含了进去
const int a = 5;
const int b = a*100;
const int c = a + b - 64;04
容易混淆的const常量定义
1. 某个量的值恒定不变:
const float x = 5.0; //定义x并将x的值初始化为5.0之后,在程序运行期间x的值将保持5.0不变2. 指针指向的地址恒定不变,但可以通过指针来修改其指向地址的值:
float x = 1.23;
//初始化指针p指向x的地址之后,p将不能改为指向其它地址
float *const p = &x;
//无效操作
float a = 6.3;
p = &a;
//有效操作
*p = 100.0; //等效于x = 100.03. 指针指向的地址可以改变,但不能通过指针来修改其指向地址的值,该情况与上述第2种情况相反:
float x = 1.23;
//初始化指针p指向x的地址之后,将不能通过指针p来修改x的值
float const *p = &x;
//有效操作
float a = 6.3;
p = &a;
//无效操作
*p = 100.0; //这样并不能修改x的值,x的值还是1.23另外,以下两种定义方式是等效的,都属于此种情况:
float const *p;const float *p;05
const常量与类
在类内部定义的const常量,仅在该类的某个对象的生命周期内是恒定不变的,对于整个类而言却是可以改变的,也即该类的不同对象可以将该常量初始化为不同的值。
声明类时,其内部的const常量成员是不能被初始化的,比如以下代码是有问题的,声明类A时len的值并不能被初始化为50,而是一个不确定的值。
class A
{
const int len = 50; //实际len的值并不能被初始化为50,而是一个不确定的值
int x[len];
}不过类内部的const常量成员可以通过构造函数的初始化表进行初始化:
class A
{
const int len;
A(int length); //构造函数
};
A::A(int length):len(length) //构造函数的初始化表
{
}
A a(100); // 对象a的len值被初始化为100
A b(200); // 对象b的len值被初始化为200 如果非要定义在类的所有对象中都恒定不变的常量,可以通过以下两种方法:
1. 使用枚举来实现,如以下代码,不过这样做的缺陷是枚举定义的len1和len2只能是整型数,不能是浮点数。
class A
{
enum { len1 = 20, len2 = 58}; //len1和len2的值在所有对象中都是不变的
int x1[len1];
int x2[len2];
};2. 使用static关键字,加上static修饰之后,常量len不再保存在存储对象的区域(堆、栈等),而是保存到了静态存储区,因此对所有该类的对象来说len是恒定不变的常量。
class A
{
static const int len = 30;
int x[len];
}欢迎关注“萌萌哒程序猴”微信公众号,接下来会不定时更新更加精彩的内容,敬请期待~
相关推荐
- win10自带文件恢复工具(win10文件恢复工具推荐)
-
步骤:第一步:打开系统的管理员命令提示符窗口。Windows10系统打开管理员命令提示符窗口有如下几种方法:方法一:在系统桌面左下角的搜索栏输入:CMD,点击:命令提示符,可以打开管理员命令提示符窗口...
- 电脑本地磁盘c盘满了怎么办(电脑本地磁盘c盘满了如何删除)
-
当您的电脑本地磁盘C满了时,可能会出现一些问题,例如无法安装新程序、无法保存文件等。以下是一些解决方法:1.删除不需要的文件:可以通过手动删除不需要的文件或使用磁盘清理工具来清理本地磁盘C。在清理磁...
- 傲游浏览器(傲游浏览器app下载)
-
1、开始——程序——找到遨游——打开,如果能打开说明快捷方式有问题2、362急救箱系统修复、网络修复傲游浏览器曾经是一个备受推荐的浏览器,由于其强大的功能和用户友好的界面,在中国的浏览器市场占有一...
- 电脑怎么定时关机软件(电脑怎样定时开关机软件)
-
给电脑设置定时开关机的方法如下:1、点击桌面左下角的开始按钮,打开“控制面板”。2、然后我们点击“系统和安全3、点击下方的“管理工具”。4、再点击“任务计划程序”。5、点击“计划任务程序库”,选择“创...
- 网易邮箱企业邮箱登录入口(网易邮箱企业免费邮箱登录)
-
网易企业邮箱官网(qiye.163.com),除此之外所看到的都是经销商网站。现阶段在该官网是可以填写信息直接开通网易企业邮箱体验试用的。如果有不明白的地方需要专人服务也是可以在官网点击在线咨询按钮或...
-
- qq电子邮箱怎么写(电子邮件信箱怎么注册)
-
1.每个人在注册QQ时都会有关联的一个邮箱,它的格式就是“QQ号码@qq.com”。2.用户可以免费开通自己的手机号码邮箱帐号。3.QQ邮箱还可以注册“……@foxmail.com”这样的商务型帐号。4.@qq.com邮箱可以有...
-
2026-01-12 22:05 liuian
- 台式机装机步骤(台式机 装机)
-
原因:1、更新的驱动不正确或未更新完成(使用USB键鼠经常发生);2、电脑更新驱动时假死,导致进程反应过慢。解决方法:1、如更新时驱动不正确,USB键盘、鼠标无作用时;可等待1~2分钟,看键鼠是否恢复...
- win8手机下载安装(win8安卓)
-
在电脑上面就可以下载,打开浏览器搜索windous8系统会出现一些下拉选择,选择第一条或者选择有官网字样的,就直接有下载按钮,然后点击下载就可以了关闭应用自动更新第一步、在系统中找到应用商店。第二...
- 台式电脑显卡怎么升级(台式电脑显卡升级方案)
-
一般情况下,建议到产品(您的显卡)品牌官网上去下载相应最新的驱动,这虽然并不能保证一定就是显卡最新的驱动,但相对于稳定性来说是首选。如果是高级玩家,追求更新、更好的性能发挥,可以利用驱动精灵一类的驱动...
- u盘数据丢失的原因(u盘数据丢失的原因有哪些)
-
U盘出现了损坏造成的磁道出现了损坏。这个U盘的磁道是最容易损坏的,有的时候你不知道怎么碰到它,它就有数据丢失了就无法显示这样的情况,你可以在电脑上进行修复,首先你点击U盘右键找到属性选择修复,这样把...
- window7下载哪个版本的ie(windows7用哪个版本的ie浏览器)
-
WIN7系统自带的IE浏览器是8.0版本的。IE全称InternetExplorer,是美国微软公司推出的一款网页浏览器。IE8扩展的新功能有:1、Activities(活动内容服务)。用户可以从网页...
- 服务器回收(上海服务器回收)
-
回收服务器内存后,首先应该彻底清除内存存储的所有数据和敏感信息,然后进行分类处理。如果内存仍然有效,可以进行检测、测试和修复后再重新使用。如果内存已损坏或过期,应该妥善处理,比如通过专业的硬件回收公司...
- 戴尔官网入口学生通道(戴尔学生渠道)
-
戴尔官网地址如下,在浏览器输入就可以加入了。DELL官方网站http://www.dell.com.cn/DELL官方旗舰店(天猫)http://dell.tmall.com/DELL官方旗舰店(京东...
- win7旗舰版激活码病毒(win7旗舰版激活密钥 永久激活码)
-
激活和破解工具会修改一些系统文件或数据,一般都会被杀毒软件识别为木马。而且现在网上的windows和office激活工具有的确实是带有木马的,最好去值得信任的网站或者论坛下载。
- 一周热门
-
-
飞牛OS入门安装遇到问题,如何解决?
-
如何在 iPhone 和 Android 上恢复已删除的抖音消息
-
Boost高性能并发无锁队列指南:boost::lockfree::queue
-
大模型手册: 保姆级用CherryStudio知识库
-
用什么工具在Win中查看8G大的log文件?
-
如何在 Windows 10 或 11 上通过命令行安装 Node.js 和 NPM
-
威联通NAS安装阿里云盘WebDAV服务并添加到Infuse
-
Trae IDE 如何与 GitHub 无缝对接?
-
idea插件之maven search(工欲善其事,必先利其器)
-
如何修改图片拍摄日期?快速修改图片拍摄日期的6种方法
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
