定义变量时,不可或缺的一个要素就是数据类型。本质上讲,这就是为了实现计算需求,我们必须先定义好数据的样式,告诉计算机这些数据占多大空间,这就是所谓“数据类型”的含义。
也可以简单理解为,我们这个数据是什么类型的,比如“3.14”,如果是浮点型,则属于算术类型,可以进行数学的运算,如果是文本型,则在运算中,他实际上并没有可用的数据
基本数据类型,主要包括算术类型和空类型(void)。其中算术类型又包含了整型和浮点型;而空类型不对应具体的值,只用在一些特定的场合,比如一个函数如果不返回任何值,我们可以让void作为它的返回类型。
整型(整数型)
整数型就是表示整数的类型
在C++中,有多个基本整型的名称:
- char
- short
- int
- long
- long long
C++标准中对它们有最小长度的要求,比如:
- short类型至少为16位(2字节)
- int至少2字节,而且不能比short短
- long至少4字节,而且不能比int短
- long long至少8字节,而且不能比long短
简单理解就是short类型,最大的值是32767,最小的值是32768,而int类型则是最大20亿左右,最小负20亿左右
如果数据超过了该类型的最大值,则会出现数据溢出。具体表现为short变量的值为正数的32768,实际上在输出(使用)该变量时,该变量的值会变为-32768,因为在2进制中加1后,全部数值都是0,换算就是short变量的最小值-32768,反之如果值为负的32769,调用时结果则会变为32767
无符号整型
整型默认是可正可负的,如果我们只想表示正数和0,那么所能表示的范围就又会增大一倍。以16位的short为例,本来表示的范围是-32768 ~ 32767,如果不考虑负数,那么就可以表示0 ~ 65535。
C++中,short、int、long、long long都有各自的“无符号”版本的类型,只要定义时在类型前加上unsigned就可以。
unsigned short a = 1;
但实际情况中,一般只需要遵循以下三个原则即可:
- 一般的整数计算,全部用int;
- 如果数值超过了int的表示范围,用long long;
- 确定数值不可能为负,用无符号类型(比如统计人数、销售额等);
char类型
char也是整型,但是它实际是通过ASCII码去换算成一个字符
比如以下代码,运算输出的结果就是A,因为根据类型,编译器会将这个类型的值换算为对应的字符。
char a = 65;
std::cout << a << std::endl;
也可以将char用作运算,以下代码就是,char类型与int类型的运算。
char a = 65;
int b = 1;
char c = a +b;
std::cout << c << std::endl;
//这里c输出的会是b
扩展知识:char类型一般没有定义有符号或无符号类型,编译器会根据实际源码自动选择,并且ASCII码只占用128位,所以有无符号影响不大。
bool类型
bool类型只有两个值,true和false(真与假),主要用于对条件的判断,换算成数字就是1代表true,false是0.
浮点类型
跟整数对应,浮点数用来表示小数,主要有单精度float和双精度double两种类型,double的长度不会小于float。通常,float会占用4个字节(32位),而double会占用8个字节(64位)。此外,C++还提供了一种扩展的高精度类型long double,一般会占12或16个字节。
除了一般的小数,在C++中,还提供了另外一种浮点数的表示法,那就是科学计数法,也叫作“E表示法”。比如:5.98E24表示5.98×1024;9.11e-31表示9.11×10-31。
字面值常量
我们在给一个变量赋值的时候,会直接写一个整数或者小数,这个数据就是显式定义的常量值,叫做“字面值常量”。每个字面值常量也需要计算机进行保存和处理,所以也都是有数据类型的。字面值的写法形式和具体值,就决定了它的类型。
整型字面值
整型字面值就是我们直接写的一个整数,比如30。这是一个十进制数。而计算机底层是二进制的,所以还支持我们把一个数写成八进制和十六进制的形式以0开头的整数表示八进制数:以0x或者0X开头的代表十六进制数。例如:
-
30 十进制数字
-
036 八进制数字
-
0x1E 十六进制数字
这几个数本质上都是十进制的 30,在计算机底层都是一样的。
区别在于开头,根据开头判断该值是什么进制
在C++中,一个整型字面值,默认就是int类型,前提是数值在int能表示的范围内。如果超出int范围,那么就需要选择能够表示这个数的、长度最小的那个类型。
具体来说,对于十进制整型字面值,如果int不够那么选择long;
还不够,就选择long long(不考虑无符号类型);
而八进制和十六进制字面值,则会优先用无符号类型 unsignedint,不够的话再选择long,之后依次是 unsigned long、longlong 和 unsigned long long.
这看起来非常复杂,很容易出现莫名其妙的错误。所以一般我们在定义整型字面值时,会给它加上一个后缀,明确地告诉计算机这个字面值是什么类型。
- 默认什么都不加,是int类型:
- l 或者 L,表示 long 类型;
- ll 或者 LL,表示 long long 类型;
- u或者U,表示 unsigned 无符号类型;
一般会用大写L,避免跟数字1混淆:而u可以和L或L组合使用。例如 9527uLL就表示这个数是 unsigned longlong 类型。
浮点字面值常量
浮点型字面值默认的类型是 double。如果我们希望明确指定类型,也可以加上相应的后缀:
- f或者F,表示 float 类型;
- l或者 L,表示 long double 类型
- 什么都不加默认就是double
这里因为本身数值是小数或者科学计数法表示,所以L不会跟long类型混
淆。
字符和字符串字面值
字符就是我们所说的字母、单个数字或者符号,字面值用单引号引起来表示。字符字面值默认的类型就是char,底层存储也是整型。
而多个字符组合在一起,就构成了“字符串”。字符串字面值是一串字符,用双引号引起来表示。
- 'A' 字符字面值
- "Hello World!" 字符串字面值
字符串是字符的组合,所以字符串字面值的类型,本质上是char类型构成的“数组”(array)。
转义字符
有一类比较特殊的字符字面值,我们是不能直接使用的。在ASCII码中我们看到,除去字母、数字外还有很多符号,其中有一些本身在C++语法中有特殊的用途,比如单引号和双引号;另外还有一些控制字符。如果我们想要使用它们,就需要进行“转义”,这就是“转义字符”。
其中,经常用到的就是符号中的问号、双引号、单引号、反斜线,还有换行符和制表符。
// 转义字符
char tchar = '\n';
cout << "tchar = " << tchar << endl;
cout << "Hello World!\t\"Hello C++!\"" << endl;
类型转换
我们在使用字面值常量给变量赋值时会有一个问题,如果常量的值超出了变量类型能表示的范围,或者把一个浮点数赋值给整型变量,会发生什么?
这时程序会进行自动类型转换。也就是说,程序会自动将一个常量值,转换成变量的数据类型,然后赋值给变量。
// 1. 整数值赋给bool类型
bool b = 25; // b值为true,打印为1
// 2. bool类型赋值给算术整型
short s = false; // s值为0
// 3. 浮点数赋给整数类型
int i = 3.14; // i值为3
// 4. 整数值赋给浮点类型
float f = 10; // f值为10.0,打印为10
// 5. 赋值超出整型范围
unsigned short us = 65536; // us值为0
s = 32768; // s值为-32768
- 非布尔类型的算术值赋给布尔类型,初始值为0则结果为 false , 否则结果为true ;
- 布尔值赋给非布尔类型,初始值为 false 则结果为0,初始值为 true 则结果为1;
- 浮点数赋给整数类型,只保留浮点数中的整数部分,会带来精度丢失;
- 整数值赋给浮点类型,小数部分记为0。如果保存整数需要的空间超过了浮点类型的容量,可能会有精度丢失。
- 给无符号类型赋值,如果超出它表示范围,结果是初始值对无符号类型能表示的数值总数取模后的余数。
- 给有符号类型赋值,如果超出它表示范围,结果是未定义的( undefined )。此时,程序可能继续工作,也可能崩溃。
暂无评论内容