2章 变量和基本类型
2.1基本内置类型
C++基本数据类型:算术类型和空类型。其中算术类型包含字符、整型数、布尔值和浮点数。空类型不对应具体的值,常用作返回类型。
2.1.1 算术类型
算术类型分为两类:整型和浮点型
C++规定了算术类型尺寸(该类型数据所占的比特数)的最小值,同时允许编译器赋予更大的尺寸。
除去布尔类型和扩展的字符型外,其他整型可以花费为signed和unsigned两种。带符号整型可表示负数,无符号整型只能表示>=0的值。其中,int short long 和long long默认都是带符号的,加上unsigned就是无符号整型,unsigned int 可缩写为 unsigned。
如何选择类型:
- 明确数值不能为负,应选用unsigned
- 整数运算时,short往往太小,而long和int一般有同样的尺寸。因此如果数值超过int的表示范围(-231 到 231-1),应选用long long
- 执行浮点运算用double ,float可能会精度不够,而double和float计算代价相差无几。
2.1.2 类型转换
Tips:C++中对象的含义是指 一块能存储数据并具有某种数据类型的内存空间,不只是类的对象,变量也可称作对象。
当在程序的某处我们使用了一种类型而其实对象应该取另一种类型时,程序会自动类型转换。
bool b = 42; //b为真
int i = b; //i为1
i = 3.14; //自动转换为整型,i为3
double pi = i; //pi的值为3.0
unsigned char c = -1; //若char占1字节 8bit,c的值为255
signed char c2 = 256; //假设char 占8bit,c2的值是未定义的
自动类型转换中,类型所能表示的值的范围决定了转换的过程:
- 布尔值好说,取值:true或false,非0或0,0为false,非0为true。
- 赋值运算右结合,以等号左边的数据类型范围为准。当把一个浮点型赋值给整型,自动进行近似处理,结果为整型能表示的精度。
- 整数值赋给浮点型,小数部分记为0.
当我们赋给无符号类型一个超出他表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。unsigned char占 8bit,克表示0至255区间内的值,如果赋区间以外的值-1,结果是-1对256取模后所得的余数。
而负数的取模运算,-1对256取模要先将-1加上256的整数倍转换为正数再取模,也就是(-1)%256 = (-1+256)%256=255%256=255
含有无符号类型的表达式
尽管不会故意给无符号类型赋值负数,但很容易写出这样的代码。
当算术表达式中既有无符号数又有int型数据时,int型数据会转换成无符号数。
unsigned u = 10; //unsigned int
int i = -42;
cout<<i+i<<endl; //-84
cout<<u+i<<endl; //如果int 占4字节 32位 输出4294967264
第一个cout常规操作,第二个要首先把int型转换为无符号数再运算。把负数转换为无符号数,其结果等于这个负数加上无符号数的模。
由于32位int表示范围-231 到 231-1,无符号int取模是4294967296,加上负数42,再加10,结果为4294967264
尽量不要混合使用带符号类型和无符号类型。
2.2 变量
变量声明与定义的关系
为了支持C++分离式编译,将声明和定义区分开来。声明使得变量名为程序所知,一个文件若使用别处定义的变量,必须包含对变量的声明。而定义负责创建与变量名关联的实体。
extern关键字
若想只声明一个变量而不是定义它,就可以添加extern关键字。常用在全局变量中,若在一个文件定义全局变量double g_num,想在另一个文件中使用,需要声明 extern double g_num;