C/C++文字常量与常变量

以下代码使用平台是Windows 64bits+VS2017。


在C/C++编程时,经常遇到以下几个概念:常量、文字常量、字面常量、符号常量、字符常量、常变量、字符串常量等,网上的资料描述的不尽相同,弄得大家云里雾里。本文将尝试为大家捋清楚以上易混淆概念的定义、关系和区别。

常量指值不可改变的量,在C/C++中常量分为两种,文字常量(Literal Constant)和常变量(Constant Variable)。 文字常量和常变量的本质区别:文字常量编译之后存储在代码段,不可寻址,常变量存储在数据区(堆、栈、BSS段或数据段),可寻址。

1.文字常量

文字常量又称为“字面常量”,包括数值常量字符常量符号常量。其特点是编译后写在代码区,不可寻址,不可更改,属于指令的一部分。

int& r=5;   //编译错误

这条语句出现编译错误,原因是文字常量不可寻址,因而无法为文字常量建立引用。下面这条语句又是合法的:

const int& r=5;

原因是编译器将一个文字常量转化成常变量的过程。在数据区开辟一个值为5的无名整型常变量,然后将引用r与这个整型常变量进行绑定。

数值常量:包括整型常量和实型常量。整型常量指常整数,有十进制、八进制、十六进制三种表示形式。实型常量包括单精度浮点数(float)、双精度浮点数(double)和长双精度浮点数(long double),表示形式有科学计数法和非科学计数法。

int a=4;            //4为数值常量中的整型常量
float b=4.4;        //4.4为数值常量中单精度实型常量
double c=1.4e10;    //1.4e5表示的值为1.4×10^5,是数值常量中双精度实型常量

字符常量:指ASCII字符,有128个,分为普通字符和转义字符。普通字符指可直接书写的字符,如’a’和’b’。转义字符指不能直接书写的特殊字符,需要使用反斜杠进行表示,比如’\t’表示水平制表符,’\v’表示垂直制表符。

符号常量:用标识符代表一个常量,使用之前必须定义。例如宏定义和枚举元素。

#define NUM 100 //NUM为符号常量,100为整型常量
enum Weekday{SUN, MON, TUES, WED, THU, FRI, SAT};   //SUN,MON等均为符号常量

2.常变量

常变量指定义时必须显示初始化且值不可修改的变量。与其他变量一样被分配空间,是可以寻址的。注意,字符串常量是常变量的一种,名称为其本身,存储在代码段,可寻址,不可修改。

cout<<&”hello world”<<endl; //打印输出字符串常量”hello world”存储地址

常变量在C/C++中由const关键字来定义,分为全局常变量和局部常变量。二者的区别在于:全局常变量存储在代码段的只读内存区域,不可修改有操作系统来保障,局部常变量存储在栈区,在编程语言语义层面上由编辑器做语法检查来保障其值不可修改,因不是放在只读内存中,可以获得局部常变量的地址,运行时间接进行修改。参考如下代码:

#include <iostream>
using namespace std;

const int con1=3;
void showValue(const int& i)
{
    cout<<i<<endl;
}

int main(int argc,char* argv[])
{
    const int con2=4;
    int* ptr=NULL;
    ptr=const_cast<int*>(&con2);
    *ptr=5;
    showValue(con2);                //1,输出5
    cout<<"con2:"<<con2<<endl;      //2,输出4
    ptr= const_cast<int*>(&con1);
    *ptr=6;                         //3,运行时错误,写入冲突
}

程序1处输出5,表明局部常量con2的值已经被修改,2处输出为结果仍然为4,并不是说明常变量con2的值没有被修改,而是因为编译器在代码优化的过程中已经将con2替换成了文字常量4。程序3处,运行时出错,表明全局常变量存储在只读内存,无法间接改写。

有关C/C++程序内存分区可参见博客程序内存布局


参考文献

[1]符号常量与常变量的区别 [2]百度百科.符号常量 [3]百度百科.字符常量 [4]百度百科.常量 [5]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SeanCheney的专栏

Python基础回顾基本数据类型和运算容器分支和循环函数、生成器和类map, reduce和filter列表生成(list comprehension)字符串文件操作和pickle异常多进程(mult

Python shell输入import this 可以看到The Zen of Python 基本数据类型和运算 基本数据类型 Python中最基本的数据类...

4677
来自专栏Golang语言社区

Golang指针与nil浅析

曾经听说过一句话,编程的本质就是指针和递归。那会刚开始编码,只是这两个的概念有个感性粗浅的认识。最早接触指针,莫过于C语言了,能否理解用好指针也成为一个合格C语...

2906
来自专栏编程

从零开始学正则

问题:我怎么才能收到你们公众号平台的推送文章呢? 正则规范 正则表达式的英文是regular expression简称regex。正则表达式就是用事先定义好的一...

1908
来自专栏Golang语言社区

Go语言基本语法

前面已经看到了Go程序的基本结构,所以这将是很容易理解Go编程语言等基本构建块。 Go令牌 Go程序包括各种令牌和令牌可以是一个关键字,一个标识符,常量,字符串...

2796
来自专栏小詹同学

Python系列之——字符串格式化(xiaozhan is a boy of 22 years old.)

不知道小伙伴有没有遇到过字符串输出有格式要求的情况呢?今天小詹学习分享一波python的字符串格式化的方法。学以致用,首先我们得明确为什么要格式化字符串输出,以...

702
来自专栏Golang语言社区

【提高篇】GO语言标准错误处理机制error用法实例

本文实例讲述了GO语言标准错误处理机制error用法。分享给大家供大家参考。具体分析如下: 在 Golang 中,错误处理机制一般是函数返回时使用的,是对外的接...

36411
来自专栏xx_Cc的学习总结专栏

iOS底层原理总结 - 探寻block的本质(二)

2834
来自专栏闵开慧

java概念1

public static void main(String[] args) {//其中[]也可以写在args后面,args也可以随便写成其他字母,例如asd...

35211
来自专栏GreenLeaves

JS框架设计之对象类型判断一种子模块

Javascript有两套数据类型,一套是基础数据类型,一套是对象数据类型。基础数据类型包括5种基本数据类型,分别是null,bool,undefined,nu...

1968
来自专栏Charlie's Road

Swift算法俱乐部:Swift栈(Stack)数据结构

翻译自raywenderlich网站iOS教程Swift Algorithm Club系列

1022

扫码关注云+社区

领取腾讯云代金券