C++中字面值常量和字面值类型

作者:zhaojia92 
来源:CSDN 
原文:https://blog.csdn.net/zhaojia92/article/details/50831436 
版权声明:本文为博主原创文章,转载请附上博文链接!


       一个形如42的值被称为字面值常量。字面值常量的形式和值决定了常量的类型。例如0x42是16进制表示的整型常量。‘a'是char型字面值。字面值常量顾名思义由字面意思表示,是常量。字面值常量在程序中是直接表示的,整型直接写出大小,字符直接写出字符。一个字面值常量在编译时被直接解析为立即数,编译器内部维护字面值常量的类型。

       常量表达式是指在编译和执行过程中,该表达式的值不会改变,且编译过程中可以立即得到其值的表达式。一部分const对象是常量表达式,由常量表达式初始化的const对象也是常量表达式。常量表达式在程序运行时不会改变,即使一个程序多次启动或外部参数发生变化,该值也不会改变。编译器在编译优化时可能把常量表达式直接替换为立即数,具体要看编译环境。一般来讲,字面值常量属于常量表达式。

       并非所有const对象都是常量表达式,const仅标记对象为只读属性,该对象在初始化后无法再改变。如果const对象所赋初值在编译阶段就可确定,那么此const对象才是常量表达式。const对象和存储位置也没有必然联系,常量可以分布在栈、堆、静态存储区中。对于声明在函数体内的const常量,如果没有被编译优化掉,该常量存储在栈中。全局的const常量存储在全局存储区。

      C++中允许将变量声明为constexpr类型以使编译器在编译时检查该变量是否是常量表达式。声明为constexpr的对象一定是常量表达式。且初始化必须用常量表达式。

例如:

   const int a = 12;    //a是常量表达式

   const int b = a+1;  //b也是常量表达式

   constexpr int c = a+b; //编译器可以在编译时期可以确定其值

   const int d = getsize();   //c不是常量表达式,编译器编译时无法确知getsize()的执行结果。

   constexpr int e = getsize();  //error! 将会报错

      字面值的类型根据字面值表达形式不同而不同,编译器根据字面值形式推断字面值的类型。字面值多数为算术类型。自定义类、IO类不属于该类型。

      对于指针字面值,其只有nullptr和NULL。指针也可以是constexpr的常量表达式,表示该指针为const且指向在编译时确定。不是所有的顶层const指针都是constexpr的。只有那些在编译时就确定地址指向的const指针才是constexpr。因此nullptr、NULL、指向固定地址的指针是constexpr的。


      对于显式指出的字符串常量,其存储在常量存储区中,例如:

      const char *const str1 = "hello"; //

      const char *const str2 = "hello"; //“hello"存储在常量存储区

      constexpr const char *str = str1; //constexpr,编译时确定的指针str

      assert(str1 == str2); //str1和str2指向相同地址

      此时的str1和str2指针都是constexpr的。那么,如何判断指针是否指向固定地址呢? 

      程序在内存中的组织形式是段,有堆栈段、数据段和代码段。对于数据指针指向数据,函数指针则指向某个代码。

       对于定义在函数体外的变量,其指针是constexpr的;此类变量要占用数据段,而程序运行时,代码段和数据段大小位置均不会改变,因此编译器可以确定地址指向,是constexpr的。此外,函数内部定义的static静态变量,也会在数据区使用固定地址,因此指针也是constexpr的。对于定义在函数内部的变量,由于要在栈中开辟内存空间,而栈的情况要看程序运行状态,因此这类变量没有确定的地址,其指针不是constexpr的。代码段不会改变,函数指针也是constexpr的。

       const/constexpr常量表达式可能在编译时直接替换为立即数;但也可能被编译为const对象,程序运行时占用内存空间。const/constexpr是否被替换为立即数或生成对象取决于编译环境和语义解析,语义不允许替换的地方便生成const对象,就如inline函数一样,不是所有inline函数都被替换。

 

猜你喜欢

转载自blog.csdn.net/songsong2017/article/details/83783251