经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C 常量
来源:cnblogs  作者:喜欢兰花山丘  时间:2018/9/25 20:33:15  对本文有异议

前言 - 引言

  每次都有点长, 不如来点短的. 轻松的, 当微型小说看的 ......

  C++ const 表示常量(编译器语法糖 or 直接崩溃), 运行时不可改变(当然程序世界没有不可改变). 

在 C 中 const 语义是不推荐变动的变量, 但不是不能改变, 更不是常量.  看论证例子:

  1. #include <stdio.h>
  2.  
  3. int main(void) {
  4. const int pi = 1314;
  5. int * ptr = (int *)&pi;
  6. *ptr = 520;
  7. printf("pi = %d\n", pi);
  8. return 0;
  9. }

输出结果如下: (如果是 .cc 在 cl 中输出是 1314, 在 g++ 段错误[时间 2018/09/19])

  1. $ gcc -g -Wall const.c ; ./a.out
  2. pi = 520

 

  上面代码, 常在 "C 中没有常量" 论证中出现 (像 1, "你好", '\0' 这些是字面量,  多数会编译到代码区)

  本篇文章主题是 C 中构建常量. 总有办法 ~ 达到效果. 能够想到强加意义就是, 真不希望变量被有

心人改动. 开始之前赠送一个不错的语法, 目前时间点在最新的 cl 和 gcc 中对此不再有 warning 

  1. #include <stdlib.h>

    /*
    Free a block allocated by `malloc', `realloc' or `calloc'. */
  2. extern void free (void *__ptr) __THROW;
  3. void buf_del(buf_t b, void * m, size_t sz) {
  4. if (b->size != sz)
  5. return free(m);
  6. ...
  7. }

return free(m); 语法源自标准手册, 在 C 中 void 也是个类型.  整体而言节约了几行代码 ~

写起来更紧凑些吧 :)

 

正文 - 思路

  基础面试常会碰到这样一个问题, C 程序中有那些存储变量的区域? (多数问程序分布区域, 挺多

的, 需要查询专业书籍, 再重温几遍高级程序员自我修养). 多数会说 普通变量在栈上, 初始化的 static

或 全局变量在初始化全局区, 未初始化 static 或 全局变量在未初始化全局区, 字符串数字字面量在代

码区. 这时候有些人会忽略 reigster 变量尝试保存在寄存器区(加分项, 自我感觉这个问题挺好, 大家都

会, super 难, 还能方便大佬引申). 同样 register 引出了我们的话题

  1. const register int hoge = 110;      

不妨修改验证一下 

  1. 1 #include <stdio.h>
  2. 2
  3. 3 int main(void) {
  4. 4 const register int hoge = 110;
  5. 5 (int)hoge = 520;
  6. 6 printf("hoge = %d\n", hoge);
  7. 7 return 0;
  8. 8 }
  1. $ gcc -g -Wall register.c
  2. register.c: In function main’:
  3. register.c:5:15: error: lvalue required as left operand of assignment
  4. (int)hoge = 520;

提示左值不可修改错误. ((int)hoge 已经被强转成左值).  不妨再来一个

  1. 1 int main(void) {
  2. 2 const register int hoge = 110;
  3. 3 int * ptr = (int *)&hoge;
  4. 4 *ptr = 520;
  5. 5 printf("hoge = %d\n", hoge);
  6. 6 return 0;
  7. 7 }
  1. $ gcc -g -Wall register.c
  2. register.c: In function main’:
  3. register.c:5:5: error: address of register variable hoge requested
  4. int * ptr = (int *)&hoge;

提示 register variable 变量没有地址, 无法转换错误. 

通过 register 构建 int, unsigned const 常量是没有问题. 那 float, double char * or struct nuion ...

且看下文 ~ 

   

  话说 register 申请放入寄存器, 不在五行之中. 毕竟空间有限, 这种奥妙玄幻用不了太多. 对

于 char * 如何处理呢. 有的朋友会抛出

  1. const char * const heoo = "hello, 世界";

这种字面量表示方式出发点是 "字面量不可变". 但恰恰编译器很多, 也有很多参数配置. 有些编译

器特定配置或默认配置是可以改变字符串字面量的. 所以这种做法是不可控的, 未定义的.

  因而构造另一种修真套路, 宏(本质还是构建左值 lvalue)

  1. #include <stdio.h>
  2. #ifndef const_str_hoge
  3. inline static const char * const const_str_hoge(void) { return "白龙马"; }
  4. #define const_str_hoge const_str_hoge()
  5. #endif
  6.  
  7. int main(void) {
  8. printf("const_str_hoge = %s\n", const_str_hoge);
  9. return 0;
  10. }
  1. $ gcc -g -Wall chas.c ; ./a.out
  2. const_str_hoge = 白龙马

是不是感觉大江随浪飘, 修真无岁月. 同样对于 float 也可以是这样 

  1. #ifndef const_float_pi
  2. inline static float const_float_pi(void) { return 3.14; }
  3. #define const_float_pi const_float_pi()
  4. #endif

再补充一个 struct

  1. #include <stdio.h>
  2.  
  3. struct version {
  4. int major; // 主版本号
  5. int minor; // 副版本号
  6. int micro; // 子版本号
  7. };
  8. #ifndef const_version
  9. inline static const struct version const_version(void) {
  10. return (struct version){.major = 1, .minor = 2, .micro = 3};
  11. }
  12. #define const_version const_version()
  13. #endif
  14.  
  15. int main(void) {
  16. printf("version = { major = %d, minor = %d, micro = %d}\n",
  17. const_version.major, const_version.minor, const_version.micro);
  18. return 0;
  19. }
  1. $ gcc -g -Wall struct.c ; ./a.out
  2. version = { major = 1, minor = 2, micro = 3}

单纯的运行时中是无法修改这些特殊构造出来的常量. 而且通过编译器无法编译通过,

也会让有心人放弃犯错误 :)  好的制度应该考虑让想犯错的如何难犯糊涂 ~ 

 

后记 - 展望

       错误是难免的, 欢迎交流 ~

  <<你一定要是个孩子>> - https://music.163.com/#/song?id=487379098

       

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号