C/ C++常量

原创 2013年12月03日 10:07:10

常用的常量可以分为:字面常量、符号常量、契约性常量、布尔常量、和枚举常量

1、字面常量

这种常量最为常见,例如直接出现的各种进制的数字、字符(‘’括住的单个字符)或者字符串(“”括住的一系列字符)等。实际上,只存在基本数据类型的字面 常量。

字面常量只能引用,不能修改,语言实现一般讲它保存在程序的符号表里,而不是一般的数据区中。符号表是“只读”的(这里不同于只读存储器,只是一种访问机制)。此外,初字符串以外,无法读取字面常量的地址。

例如 int *p = &5;                             //错误,不能读取字面常量的地址

         char *pChar   = "abdcef";       //正确,取字符串的地址。注意,这里不是给一个字符串变量,字符数组初始化

         char c[7]        = "abdcef";       //正确,一个字符数组初始化。

         *(pChar+2)= 'k';                 //错误,不能修改字面常量的内存单元

2、符号常量

存在两种符号常量:用#define定义的宏常量和用const定义的常量。由于#define是预编译伪指令,它定义的宏常量在进入编译阶段前就已经被替换为所代表的字面常量,因此宏常量在本质上是字面常量。

在c语言中,用const定义的常量其实是值不能修改的变量,因此会给它分配存储空间(外连接的);但是在c++中,const定义的常量要具体情况具体对待:对于基本数据类型的常量,编译器会把它放到符号表中而不分配存储空间;而ADT/UDT(一个协议的参考实现)的const对象则需要分配内存空间(大对象)。还有一些情况也要分配存储空间,例如强制声明为extern的符号常量或者取符号常量的地址等操作,都将强迫编译器为这些常量分配内存空间,以满足用户需求。

可以对一个const常量取地址:对于基本数据类型的const 常量,编译器会重新在内存中创建一个它的拷贝,通过其地址访问的是这个拷贝而非原始的符号常量;而对于构造类型的const 常量,实际上它是编译时不允许修改的变量,因此如果能绕过编译器的静态类型安全检查机制,就可以在运行时修改其内存单元:

例如:

const long lng   = 10;

long *pl = (long*)&lng;                            //取常量的地址

*pl = 1000;                                             //迂回修改

cout<< *pl <<endl;                                  //1000,修改的拷贝的内容

cout<< lng<<endl;                                  //10,原始常量没有变

class Interger{

public:

        Interger():m_lng(100){}

        long m_lng;

}

const  Interger int_1;               

Interger *pInt = (Interger*)&int_l;            //去除常数属性

pInt->m_lng = 1000;                                   //迂回修改

cout<< pInt->m_lng <<endl;                       //1000,修改const对象

cout<< int_1.m_lng <<endl;                        //1000,迂回修改成功

3、契约性常量

用const修饰函数返回值,如果给“指针传递”的函数返回值加const那么函数返回值是一种契约性常量,不能直接被修改,并且该返回值只能被赋值给加const修饰的同类型指针(除非强制转型)。例如:

const char *GetString(void);

char *str = GetString();                         //错误;

const char* str = GetString();                //正确;

//=======================================================================

//测试环境 windowsxp,vc6.0

/*int Stringlength(const char *s)*/

#include<iostream>
#include <stdlib.h>

using namespace std;

int Stringlength(const char *s)
{

 cout<<s<<endl;     //输出值s并非字符串地址,而是字符串,注意C++/C默认char* 表示字符串
 if(s == NULL) exit(1);

 int length = 0;

 char *base = (char *)s;      //这里是将s的类型强制转换了,如果不强制转换应该为const char *base = s;

 while((*base++) != ' \0 ' )  length++;
 return length;
}
void main()
{
 char *ch = "Hello,c++ world!";     //取字符串常量的地址
 cout<<ch<<endl;                       //输出的是整个字符串
 cout<<*ch<<endl;                      //输出的是字符串的首个字符
 int len = Stringlength(ch);
 cout<<len<<endl;
}

运行结果:

在“引用传递”时,也存在契约性常量:例如

void ReadValue(const int& num)

{

cout<<num;

int main()

{

      int n = 0;

      ReadVaule(n);           //契约性常量,n被看做是const

}


4,枚举常量

enum Gigantic

{

    SMALL = 10,

    GIGANTIC = 100000000

};

5、布尔常量

布尔常量只有两个 false和true,大小写不敏感。

总结:

        const与#define都可以用来定义常量,但是前者有更多优点:

(1)const有数据类型,而宏常量没有。编译器可以对前者进行静态安全检查;

(2)有些集成化调试工具可以对const常量进行调试,而对宏常量不可以

(3)被const修饰的东西都受到c++/c语言实现的静态安全检查机制的强制保护,可以预防以外修改。


C/C++ 常量指针,指针常量

在这里就不再重复C/C++ 常量指针,指针常量的概念了,以下以一个例题作为讲解, 题目是华为的一个选择题: 刚开始我一直以为答案是C,D一样,但是经过分析后,我产生了较大的困惑,希望能得到大神...
  • asxutao
  • asxutao
  • 2015年09月04日 11:39
  • 1424

C#学习日记20----static静态变量 与 常量

在上一篇  委托(Delegate)类型     中我定义public方法的时候使用了 static 关键字,导致后来无法通过 对象.方法名  的形式访问此方法,这一篇我们就具体学习下 stati...
  • HC666
  • HC666
  • 2015年10月11日 11:25
  • 2896

C++常量(C++数值常量、字符串常量、符号常量)

数值常量 数值常量就是通常所说的常数。在C++中,数值常量是区分类型的,从字面形式即可识别其类型。 整型常量(整数)的类型 在上一节中已知道:整型数据可分为int, short int,long...
  • worisaa
  • worisaa
  • 2017年02月07日 19:38
  • 2120

[价值百元][连载]c/c++/c#程序员实用大全(第二章 宏与常量)

  • 2011年04月19日 09:58
  • 544KB
  • 下载

C/C++语法知识精华整理(1)-左值与右值、变量与常量、 define与const、Printf特点、补码与阶码、位运算等

1.左值与右值的区别 左值可以放在左边赋值的值。右值可以放在右边的值。 左值,没有内存实体的左值不存在的。Int a=3; 右值,可以有内存实体,也可以没有内存实体. A+1,&a,100,右值,都在...
  • zachary8368
  • zachary8368
  • 2015年08月04日 22:58
  • 217

C/C++几个常见概念分析(指针、引用 、const常量、#define)

(一):指针与引用的区别                 指针是什么,指针是一个变量(A)他值表示的是另一个变量(B)的地址。                 引用是什么,引用是一个变量(B)的另一个...
  • lanxueCC
  • lanxueCC
  • 2015年01月21日 20:28
  • 872

C/C++中,内存中数据存储分成4个区:堆、栈、全局/静态存储区和常量存储区。

栈(stack),就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。      堆(heap),一般由程序员分配释放,若程序员不释放,程序...
  • zifuttt
  • zifuttt
  • 2012年04月01日 10:29
  • 3698

定义C/C++全局变量/常量几种方法的区别(转)

在讨论全局变量之前我们先要明白几个基本的概念: 1. 编译单元(模块):     在IDE开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错误(LI...
  • SBWCD_0803
  • SBWCD_0803
  • 2012年08月19日 23:01
  • 694

C/C++定义全局变量/常量几种方法的区别

在讨论全局变量之前我们先要明白几个基本的概念: 1. 编译单元(模块)        在IDE开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错...
  • chenlong12580
  • chenlong12580
  • 2012年07月05日 00:08
  • 2776

c/c++中extern、static、const的用法及全局变量/常量

基本概念 编译单元 由.cpp(.c)文件及include的.h文件构成一个编译单元(把头文件内容复制到cpp中),在编译时,编译为一个.obj文件,obj文件里包含了变量存储的相对地址。 声明与定...
  • lwwl12
  • lwwl12
  • 2017年07月28日 13:06
  • 179
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C/ C++常量
举报原因:
原因补充:

(最多只允许输入30个字)