单片机/C语言八股:(十四)const 关键字的作用(和 define 比呢?)
上一篇下一篇C 语言实现矩阵乘法目 录const 关键字的作用和 define 比呢1const 修饰变量① 局部变量函数内部② 全局变量文件作用域2const 与指针的组合重点难点3const 修饰函数① 修饰函数参数② 修饰函数返回值4const 修饰数组和结构体① 常量数组查找表、配置表② 结构体成员为 const较少用但合法5const 与 #define 的区别6总结const 关键字的作用和 define 比呢constant[adj] 固定的、不变的[n] 常数、常量被 const 定义后本质上还是变量只是无法修改。在必须应用常量的情况下是无法使用的所以叫做常变量。总结在最后面在 C 语言中const是一个类型限定符type qualifier用于声明某个对象为只读read-only。这意味着该对象的值在初始化后不能被程序直接修改。如果尝试修改编译器会报错除非通过强制类型转换绕过但这是未定义行为应避免。1const 修饰变量① 局部变量函数内部voidfunc(void){constintMAX_RETRY5;// MAX_RETRY 10; // 编译错误不能修改 const 变量}用 const 修饰的局部变量依旧存储在栈上但内容不可写具有明确类型比如int。② 全局变量文件作用域// file.cconstdoublePI3.1415926;默认仅在本 .c 文件可用相当于隐含static若需在多个文件共享需配合extern声明。在 .c 文件中定义在对应的 .h 文件中依旧要使用extern// constants.hexternconstdoublePI;// constants.cconstdoublePI3.1415926;// main.c#includeconstants.hdoublerPI*2;2const 与指针的组合重点难点const与指针结合时位置决定含义。记住口诀const在*左边内容不能改但指针可以改const在*右边指针不能改但内容可以改*两边都有const内容和指针都不能改。声明含义能否修改指针能否修改指向的内容const int *p或int const *p指向常量的指针✔️ 可以p x;❌ 不可以*p 10;错误int *const p x;常量指针❌ 不可以✔️ 可以*p 10;const int *const p x;指向常量的常量指针❌ 不可以❌ 不可以应用示例constchar*strHello;// 推荐写法字符串字面量是只读的// str[0] h; // × 运行时可能崩溃写只读内存strWorld;// √ 指针可变charbuffer[10];char*constptrbuffer;// 指针固定指向 bufferptr[0]A;// √ 内容可变// ptr another_buffer; // × 指针不可变3const 修饰函数这是const最重要的应用场景之一表达“只读”契约。① 修饰函数参数指针参数加 const指针参数就是形如void func(const int* x)voidprint_array(constintarr[],size_tn){for(size_ti0;in;i)printf(%d ,arr[i]);// √ 只读访问// arr[0] 999; // × 编译错误}等价于const int *arr表明函数不会修改传入的内容调用者可安全传入常量数组或普通数组。字符串处理函数的标准做法size_tmy_strlen(constchar*s);// 不修改 sintmy_strcmp(constchar*s1,constchar*s2);// 不修改 s1, s2所有标准库如strlen,strcpy,printf等对只读参数都使用const。值参数非指针参数加 const 对实参没啥影响但形参在函数内部不会被修改值参数就是形如void func(const int x)入口参数不是指针类型的。对于传入的变量实参C 函数参数默认是 “按值传递” 当你调用一个函数时实参的值会被复制到形参中这个传入的变量实参本来就不会被修改加不加const都一样。对于形参来说形参是函数内部的一个对实参的局部变量副本给值参数加const的效果等于在函数内部给局部变量加const表示在函数体内不能修改这个值。② 修饰函数返回值修饰返回的指针 —— 有意义constchar*get_version(void){returnv1.2.3;// 字符串字面量是只读的}返回const char*表示调用者不得修改返回的字符串其他类型类似。但不要返回局部变量的 const 指针constchar*bad_func(void){charbuf[10]temp;returnbuf;// ❌ 返回栈地址函数返回后无效}修饰返回的基本类型 —— 无意义constintgetValue(void){return42;}intxgetValue();函数返回的是临时值右值表示“临时值、计算结果”如字面量42字符串字面量天生就是 const 无法被赋值const 多余。C 标准允许但毫无作用现代编译器会忽略。4const 修饰数组和结构体① 常量数组查找表、配置表constuint8_tCRC_TABLE[256]{0x00,0x07,0x0E};编译器通常将其放入.rodata段只读数据段节省 RAM。适用于嵌入式系统中资源受限场景。② 结构体成员为 const较少用但合法structDeviceConfig{constintbaud_rate;constchar*constname;};// 初始化必须在定义时完成C99 支持复合字面量structDeviceConfigdev{.baud_rate115200,.nameUART0};// dev.baud_rate 9600; // × 错误5const 与 #define 的区别const是有类型、有作用域、可取地址的运行时常量本质是常变量在 C 中不是编译时常量而#define是无类型、无作用域、纯文本替换的预处理宏在必须使用编译时常量的地方const不可用。具体如下特性const变量#define宏类型有明确类型如const int无类型纯文本替换作用域遵循 C 作用域规则块、文件全局有效从定义到#undef存储占用内存除非被优化掉不占用内存预处理阶段替换取地址可以PI合法不可以宏不是对象调试调试器可查看符号和值调试器看不到宏已被替换安全性编译器检查类型和修改无任何检查易出错初始化运行时或编译时初始化必须是常量表达式数组大小C 标准中不能用于定义数组大小除非是 VLA 或 C23可以#define N 10int arr[N];示例对比使用#define传统方式#defineMAX_SIZE100#definePI3.14159intbuffer[MAX_SIZE];// √ 合法常量表达式使用const更安全但有限制constintMAX_SIZE100;// int buffer[MAX_SIZE]; // × C89/C99 中错误const 不是“编译时常量”关键点⚠️ 在 C 语言中const变量不是编译时常量因此不能用于数组长度除非是变长数组 VLAC99、case标签、位字段宽度等需要常量表达式的地方。解决方案✔️ 对于需要编译时常量的场景如数组大小仍需用#define或enum。对于运行时常量或需要类型安全的常量优先用const。推荐实践// 数组大小、开关选项 → 用 #define 或 enum#defineBUFFER_SIZE256enum{MAX_USERS10};// 数学常量、配置值 → 用 constconstdoubleEARTH_RADIUS_KM6371.0;constcharVERSION[]1.0.0;6总结在 C 语言中const的核心作用是声明只读对象通过类型系统告诉编译器和程序员该数据在初始化后不应被修改。它主要用于修饰指针参数防止函数意外修改传入的数据定义具有类型安全的常量变量替代部分宏以及返回只读指针保护内部数据不被外部篡改。const是有类型、有作用域、可取地址的运行时常量本质是常变量在 C 中不是编译时常量而#define是无类型、无作用域、纯文本替换的预处理宏在必须使用编译时常量的地方const不可用。强制类型转换可绕过const但属未定义行为可能崩溃或静默失败。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2427454.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!