• 读《高质量C/C++》 常量


    常见的C/C++常量有:字面常量,符号常量,契约常量,枚举常量。
    1、字面常量
    字面常主要有基本数据常量、字符常量以及字符串常量,他们都会存储在程序的只读符号表中(非数据区)。
    int  age   = 27     ; // 基本数据常量
    char sex   = 'm';           // 字符常量
    char *name = "chen" ; // 字符串常量
    // 如果试图修字符串常量( 仅能试图修改字符串常量,因为只能获取到字符串常量的地址,char *sex = &'m'; int *age = &27;都会报错 ):
    printf( "试图修改指针:0x%p,指向内容\r\n",(name+0) );
    *( name+0 ) = 'C';
    // 编译不报错,运行时信息如下:
    // 输出:修改指针:0x00417830, 指向内容
    // 引用程序错误:"0x00414513"指令引用的"0x00417830"内存。该内存不能为"written"。
    // 修改字符常量同理,如有兴趣可以尝试一下。
    另外这里多讨论一种情况,如下例:
    char name[]="chen";
    printf( "原始内容:%s\r\n",name );
    printf( "修改指针:0x%p, 指向内容\r\n",(name+0) );
    *(name+0) = 'C';
    printf( "修改之后的内容为:%s\r\n",name );
    // 输出内容如下:
    // 原始内容:chen
    // 修改指针:0x0012FF48, 指向内容
    // 修改之后的内容为:Chen
    (请不要诧异这种情况,这里char name[]="chen";进行的操作是用字符串常量来初始化字符数组,所以并不是对字符串常量进行修改,只是对字符串数组进行修改,所以修改成功 )
    小结:字面常量存储在只读符号表中,不能修改能够得到的常量地址所指向的值。
    问题:什么是只读符号表?从内存地址来看,是接近静态数据区的,但不知道具体是什么东东。
    2、符号常量
    通过const或者define自定义的常量(宏)
    const double EPSILON = 1e-6; // const  定义的常量
    #define NULL 0 // define 定义的宏( 宏定义的常量,在预编译阶段就替换成对应的内容,所以本质为字面常量 )
    这里分享一下对const的认识。
    首先,C中表示不能修改的变量,因此会为此分配内存空间;
    其次,C++中针对基本数据类型不分配存储空间(存储在符号表中),大数据或者extern的符号常量需要分配内存;
    最后,const是编译时的一种手段,无法避免运行时的修改;
    通过测试,C++在运行时对整型的处理和对浮点数的处理是有区别的,如下测试:
    do{
    #define out_put( out,tmp,typeStr,type,t ) do{ \
    printf(""##typeStr":old=%"##t"\r\n",(type*)(out)); \
    *(tmp)=10;\
    printf(""##typeStr":new=%"##t"\r\n",(type*)(out));\
    }while(0);
    // 整型测试
    const char c_const = 'c';
    const bool b_const= false;
    const int i_const = 1;
    // char
    char *tChar=(char*)&c_const;
    out_put( c_const,tChar,"int",int,"c" );
    // bool
    bool *tBool=(bool*)&b_const;
    out_put( b_const,tBool,"bool",bool,"d" );
    // int
    int *tInt = (int*)&i_const;
    out_put( i_const,tInt,"int",int,"d" )
    }while(0);
    测试结果:
    do{
    int:old=c
    int:new=c
    bool:old=0
    bool:new=0
    int:old=1
    int:new=1
    }while(0);
    结论:对于整型基础数据在运行时并没有得到改变,高质量C++中描述的是,基本数据常量是保存在符号表中,编译器会为他创建一个拷贝,通过其地址访问到的就是拷贝,而非原始符号常量。
    然而对于浮点数的处理,如下测试:
    do{
    // 浮点型测试
    const float f_const = 1.0f;
    const double d_const = 1.0f;
    float *tFloat=(float*)&f_const;
    printf("old float:%.1f\r\n",f_const);
    *tFloat = 10.1F;
    printf("new float:%.1f\r\n",f_const);
    double *tDouble=(double*)&d_const;
    //out_put( &d_const,tDouble,"double",double,"f" );
    printf("old Double:%.1f\r\n",d_const);
    *tDouble = 10.1F;
    printf("new Double:%.1f\r\n",d_const);
    }while(0);
    测试结果:
    do{
    old float:1.0
    new float:10.1
    old Double:1.0
    new Double:10.1
    }while(0);
    结论:对于浮点数据在运行时得到了改变,浮点是有别于基本数据类型的,和自定义大数据类型都能在运行时进行修改。
    3、契约常量
    契约常量主要应用于带型参的函数声明,其实参本身没有使用const关键字,但被看作const对象。
    void constTest( const int &num ){ ... }
    int  num = 300;
    constTest( num );
    4、枚举常量
    enum COLOR{
    RED   = 0xFF0000,
    GREEN = 0X00FF00,
    BLUE  = 0x0000FF,
    }
    printf("color:red 0x%x\r\n",RED   );
    printf("color:grn 0x%x\r\n",GREEN );
    printf("color:blu 0x%x\r\n",BLUE  );
    最后,在谈谈类中的常量。
    首先,非静态的常量是属于每一个对象的,在每个对象的生存期内,并且它的初始化只能在初始化列表中进行;
    其次,在类中想建立常量,可以通过静态常量和枚举来实现。
    例如:
    class constClass
    {
    public:
    const int num;
    static const int id = 100;
    enum _E_CONST{
    BLUE  = 0x0000FF,
    GREEN = 0X00FF00,
    RED   = 0xFF0000,
    };
    constClass():num(200){ 
    printf("color:red 0x%x\r\n",RED   );
    printf("color:grn 0x%x\r\n",GREEN );
    printf("color:blu 0x%x\r\n",BLUE  ); 
    };
    constClass &operator=( const constClass &cc ){};
    ~constClass(){};
    };
    测试:
    constClass *cc = new constClass();
    constClass *cc1 = new constClass();
    printf("const 0x%p =  %d\r\n",&cc->num,cc->num);
    printf("const 0x%p =  %d\r\n",&cc1->num,cc1->num);
    printf("static const 0x%p =  %d\r\n",&constClass::id,constClass::id );
    printf("red =  0x%x\r\ngreen =  0x%x\r\nblue =  0x%x\r\n",constClass::RED,constClass::GREEN,constClass::BLUE );
    delete cc;
    delete cc1;
    输出:
    color:red 0xff0000
    color:grn 0xff00
    color:blu 0xff
    color:red 0xff0000
    color:grn 0xff00
    color:blu 0xff
    const 0x003965D8 =  200 // 非静态常量属于每一个对象
    const 0x00394858 =  200 // 非静态常量属于每一个对象
    static const 0x00416830 =  100 // 静态常量实现的恒定常量
    red =  0xff0000 // 枚举实现的恒定常量
    green =  0xff00 // 枚举实现的恒定常量
    blue =  0xff // 枚举实现的恒定常量
  • 相关阅读:
    轻量级分布式任务调度框架(二、LTS编译、打包、部署)
    轻量级分布式任务调度框架(一、LTS简介、特点、工作流程)
    MySQL数据库学习一
    Navicat 连接 SQL Server 数据库,报错 08001
    noVNC 遇到一个错误: Uncaught TypeError: Cannot read property 'forEach' of undefined
    加强自己VPS服务器安全的一次经历
    Python 编码错误的本质和解决方案
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'data' at line 1
    requests爬虫请求报错:UnicodeEncodeError: 'latin-1' codec can't encode character 'u2026' in position 30
    docker无法删除镜像,Error: No such container,附docker常用命令
  • 原文地址:https://www.cnblogs.com/CHENYO/p/2645790.html
Copyright © 2020-2023  润新知