C++ 变量和常量

一、变量
程序运行时,所需的数据要放在内存值才能使用,内存被格式化成一个个小的存储单元,数据保存在这些存储单元中。
这些存储单元被编上序号(内存地址)。
高级语言设计的程序不能直接通过地址来访问所保存的数据、向单元中写数据。
为了访问这些数据,必须给内存中的存储区域命名,用标识符来标志它。
存储区域存放的数据可以读取、修改、写入,则此标识符被称为变量。
变量不仅向编译器宣告变量的存在,同时为它分配所需的存储空间。
变量的类型决定类怎么去理解和操作该变量和该变量所对应的数据,
变量名为程序提供了内存块的首地址和操作它的媒介。
编译时,编译器把该名字与其对应的存储区块的地址一起放到符号表中,当需要访问该变量时,编译器就到符号表中去查找。

变量的声明
变量声明:只是向编译器说明将有一个变量存在,而不为它分配所需的存储空间,仅起占位符的作用。
格式: extern type var1,var2,…;
extern 是 C++ 的关键字,表示定义的变量是 “外部”(要么中另一个文件中,要么在本文件后面某处)的,
使用关键字 extern 声明一下变量,可以先使用后定义,可以避免编译时报告变量不存在的错误。

注:
1、因为变量的声明并没有给变量分配存储空间,所以不能在声明时给它赋初值,因为它实际上还不存在。
2、如果用 extern 声明类某个变量,则必须确保这个变量真的存在于 “外部” 中,并被 #include 指令包含进来,或真的存在于本文件后面某处。

例:
创建 test.cpp 文件:
#include
using namespace std;
#include “test.h”
extern int a;
extern int b;
int main(void)
{
int c = 2; //定义变量 c
cout << “a = ” << a <<endl; //变量 a 时声明,在另一个文件内
cout << “b = ” << b <<endl; //变量 b 是声明,在本文件后面
cout << “c = ” << c <<endl; //变量 c 是定义
return 0;
}
int b = 1; //定义变量 b
创建 test.h 文件,并放在 test.cpp 同一目录下:
#include
using namespace std;
int a = 3;
然后 gcc test.cpp 即可

变量的存储
变量的存储:变量从哪里得到保存数据所需的内存空间,以变量的定义方式而定。
1、如果变量定义在函数体内,且无 static 修饰,则该变量将从堆栈中得到存储空间。当程序执行进入函数后,才为变量分配存储空间。退出后,自动释放分配的空间。
2、如果变量定义时被 static 修饰,则无论是在函数体内,还是函数体外,都将从全局空间中得到存储空间。
3、如果变量定义在函数体外,则在全局内存空间中得到存储空间。

例:
#include
using namespace std;
double d1,d2; //定义变量 d1 和 d2
static int s1; //定义静态变量 s1
int main(void)
{
static char ch; //定义静态变量 ch
int s2; //定义变量 s2
d1 = 3.14; //使用在 main() 外部定义的变量
d2 = d1;
d1 = d1 + d2;
s1 = 10; //使用在 main() 外部定义的静态变量
ch = ‘a’; //使用在 main() 内部定义的静态变量
s2 = 1;
return 0;
}

注:
变量 d1、d2、s1 定义在函数体内,所以存储于全局内存中,
ch 虽然定义函数体内,但有关键字 static 修饰,所以也放在全局内存中,
s2 在函数体内定义又无 static 修饰,所以将从堆栈中得到存储空间。

每一个变量,都有两个信息与其相关联:
数据值(右值):变量的数据值就是存储在变量对应的存储单元中的数据。右值意指被读取,既在赋值运算符的右边,代表的是数据。
地址值(左值):变量的地址值就是变量对应的存储单元的首地址。左值意指被写入,既在赋值运算符的左边,代表的是地址。

按变量的作用域划分
1、局部变量(自动变量):在函数内部或函数参数中定义,存储在堆栈中,在程序进入函数时才分配空间,退出时就释放。不同的函数内可以有相同名称的局部变量。
2、全局变量:定义在函数外部,存储在固定的存储区域内,具体由编译器来决定,在程序的生存期内都有效,除非手工释放,否则直到程序运行结束才释放所占空间。全局变量绝不重名。

按变量的存储位置划分
1、全局空间变量:就是全局变量,存储在某一固定区域内,全程有效,用 extern 关键字声明的变量属于全局空间变量的一种。
2、堆栈空间变量:就是局部变量,存储在函数自有的堆栈空间内。
3、寄存器变量:数据保存在 CPU 的寄存器内的变量,用关键字 register 说明,也是局部变量,仅限于整型和字符型。操作速度快,但不能定义太多,也不能长久占据。

按变量的存储方式划分
1、静态变量:用关键字 static 说明,在程序所占据的数据段(Data Segment,在内存中某处保留的一段大小固定的空间)内分配永久存储空间,整个执行过程中都不释放。静态变量分为:
1.1、静态局部变量:只在定义它的函数或语句块内有效,只在第一次调用时定义,以后每次调用函数时都不再重新定义,仍然保留上次函数调用结束时的值(静态局部变量时有记忆的)。
1.2、静态全局变量:只在定义它的文件内全程有效,在整个运行期间均存在并且保持原来的存储单元位置不变,因此不能用 extern 关键字从其他文件中引用静态全局变量。
2、动态变量:用关键字 auto 说明,且 auto 一般省略,自动变量的赋值时在函数调用时进行的,每调用一次就重新赋值一次。

例:
int a = 100 ; //定义变量 a
extern int b ; //引入外部变量 b
static int c ; //定义静态变量 c
extern int d ; //引入外部变量 d
int main(void)
{
register int g = 100 ; //定义寄存器变量 g
cout << “g = ” << g << endl ;
cout << “d = ” << d << endl ;
cout << “a = ” << a << endl ;
return 0 ;
}
int d = 100 ;
注:
a 是全局变量,可以被引出到其他文件中,
b 是从外部引入的,也是全局变量,
c 是静态全局变量,只在本文件内有效,不能引出到其他文件中,
d 是用 extern 声明的全局变量,其定义在 main() 函数后,
g 是寄存器变量。

变量初始化:
变量被定义后,就在内存中给它分配类一块存储单元,用于存放数据,他可能包含预料不到的数据(曾经存储在其中过的数据)。
因此直接使用而不初始化的话,可能会数据越界、堆栈溢出等。
注:
一般编译器会默认给没初始化的变量 0(int、float型时)或 NULL(字符型时)

二、常量

1、符号常量:用标识符代替程序中保持不变的数据,用 #define 来说明,属于宏定义的范畴。
格式:#define NAME expression
例:
#define _PI_ 3.1415926
#define e 2.71828
#define MAX (100+1) //加括号时 2*MAX=202 ; 不加括号时 2*MAX=201
注:
1、末尾不加分号
2、定义的常量没有类型,内存中不存在以符号常量命名的存储单元,因此不能进行类型检查
3、给出的时立即数,不可寻址,预处理时直接进行替换,因此出现几次就有几个副本
4、运行时常量表中没有用 #define 定义的常量,因此系统不会给它分配内存,但它的副本会占据内存
5、它定义的常量是全局的,全程有效
6、当 expression 中有运算时,必须加 (),不然会出逻辑问题。因为 #define 定义的常量是宏,完成的是直接宏替换。
7、用 #define 说明的常量可以用 #undef 指令取消
8、实现的是符号到值的替换,并没有给它分配任何存储空间,定义时符号的值必须确定,不存在初始化的说法

2、常变量:内容不变的变量,在变量的定义前面加 const 修饰符即可。只能赋一次值,不能修改,具有变量的一切性质。
格式:const type var=value;
注:
1、它有类型,便于编译器进行类型检查
2、可以寻址,即使出现多个副本,只需分配一次空间
3、可以在任何地地方定义常量,编译器像对待变量一样处理它,只是分配内存的地方不同而已
4、在内存中存在着以它命名的存储单元,除非在语句中出现,否则编译时不会为它分配空间
5、一旦定义完就不能修改,所以必须赋初值,且一定要在定义语句中赋值(唯一的初始化机会)
6、程序运行时,它被记录在专门的常量表中
7、常变量在静态区分配存储空间,不像变量时在堆栈中

用 const 说明常量有两点好处:
1、如果编译程序知道一个变量的值不会改变,就会在编译时对它进行优化
2、编译程序会力图保证该变量的值不会因为程序员的疏忽而被改变

1、#define 定义的符号常量才是真正意义上的常量,其目的就是为了用标识符代替一个不变的常量,
2、const 说明的常变量,更多的目的时为了保护和优化
3、#define 时 C 语言中采用的方法, C++ 更多用的时 const 定义常变量,C++ 保留 #define 以兼容 C,推出 const以替代 #define

有些调试工具可以调试常变量,不能调试符号常量,
因为符号常量在编译时就进行了符号到数据的替换,编译后,符号常量已不存在,取而代之的是它所保存的常数。

除了在定义时,否则不能将 const 修饰的对象、引用和指针作为赋值表达式的左值,即不能出现在赋值运算符的左边

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值