zoukankan      html  css  js  c++  java
  • C 常量

    前言 - 引言

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

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

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

    #include <stdio.h>
    
    int main(void) {
        const int pi = 1314;
        int * ptr = (int *)&pi;
        *ptr = 520;
        printf("pi = %d
    ", pi);
        return 0;
    }

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

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

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

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

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

    #include <stdlib.h>

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

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

    写起来更紧凑些吧 :)

    正文 - 思路

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

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

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

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

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

        const register int hoge = 110;      

    不妨修改验证一下 

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

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

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

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

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

    且看下文 ~ 

       

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

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

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

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

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

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

    #include <stdio.h>
    
    #ifndef const_str_hoge
    inline static const char * const const_str_hoge(void) { return "白龙马"; }
    #define const_str_hoge const_str_hoge()
    #endif
    
    int main(void) {
        printf("const_str_hoge = %s
    ", const_str_hoge);
        return 0;
    }
    $ gcc -g -Wall chas.c ; ./a.out
    const_str_hoge = 白龙马

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

    #ifndef const_float_pi
    inline static float const_float_pi(void) { return 3.14; }
    #define const_float_pi const_float_pi()
    #endif

    再补充一个 struct

    #include <stdio.h>
    
    struct version {
        int major; // 主版本号
        int minor; // 副版本号
        int micro; // 子版本号
    };
    
    #ifndef const_version
    inline static const struct version const_version(void) {
        return (struct version){.major = 1, .minor = 2, .micro = 3};
    }
    #define const_version const_version()
    #endif
    
    int main(void) {
        printf("version = { major = %d, minor = %d, micro = %d}
    ", 
            const_version.major, const_version.minor, const_version.micro);
        return 0;
    }
    $ gcc -g -Wall struct.c ; ./a.out
    version = { major = 1, minor = 2, micro = 3}

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

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

    后记 - 展望

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

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

           

  • 相关阅读:
    [转]c++访问python3-实例化类的方法
    【转】利用Boost.Python将C++代码封装为Python模块
    [转]Linux下Python与C++混合编程
    [转]Windows下使用VS2015编译openssl库
    [转]boost::python开发环境搭建
    [转]linux下编译boost.python
    [转]阿里巴巴十年Java架构师分享,会了这个知识点的人都去BAT了
    [转]Python3《机器学习实战》学习笔记(一):k-近邻算法(史诗级干货长文)
    [转]马上2018年了,该不该下定决心转型AI呢
    [转]PostgreSQL命令行使用手册
  • 原文地址:https://www.cnblogs.com/life2refuel/p/9675285.html
Copyright © 2011-2022 走看看