【深度C++】之“类型与变量”

0. 何谓“数据类型”

程序的主要功能就是处理数据,要处理数据就选输入数据、输出数据。

数据类型是程序的基础,它告诉我们数据的意义以及我们能在数据上执行的操作(运算)

C++中支持广泛的数据类型,如下图(参考《C++ Primer 第5版》):

在这里插入图片描述
本文主要介绍基本内置类型相关的内容,关于自定义数据类型复合类型相关内容,因为内容繁多,会整理成其他文章。

1. 基本内置类型

1.1 算数类型

1.1.1 尺寸与机器实现
1.1.1.1 基本内置类型的尺寸

C++标准没有规定基本内置类型的尺寸和大小,只规定了尺寸的最小值,允许编译器赋予这些类型更大的尺寸。

(参考《C++ Primer(第5版)》)

类型含义最小尺寸
bool布尔类型未定义
char字符8位
wchar_t宽字符16位
char16_tUnicode字符16位
char32_tUnicode字符32位
short短整型16位
int整型16位
long长整型32位
long long长整型64位
float单精度浮点数6位有效数字
double双精度浮点数10位有效数字
long double扩展精度浮点数10位有效数字

C++规定

  • 一个int至少和一个short一样大;
  • 一个long至少和一个int一样大;
  • 一个long long至少和一个long一样大。

那么,数据到底是如何存储在计算机的内存中的呢?

1.1.1.2 内置类型的机器实现

计算机以二进制存储数据:

01001011001010100010101001000110 ...
// 0x4B2A2A46

大多数计算机以8位二进制(1个字节,byte)为一个单元访问处理数据

在这里插入图片描述

左侧的数字表示每个字节的地址,计算机通过该地址一次访问到8bit的数据。

假设在某平台上,计算机以小端方式存储:

  • 若一个int是32bit,则地址736424 - 736427的内容是1261054534
  • 若一个char是8bit,则地址736424显示的内容是字母K,地址736427的内容是F
1.1.2 signed与unsigned

除去布尔类型和扩展的字符型之外,其他的整型可以划分为有符号(signed)无符号(unsigned) 两种。

类型int、short、long和long long默认带符号,添加unsigned关键字可以将其修饰为无符号。

unsigned int ui = 80;

类型char、signed char和unsigned char是三种不同的类型,char表现为signed char和unsigned中的任意一种,由具体编译器决定。

无符号类型不会小于0,因为在机器实现上,计算机将首位地址作为符号位,0正1负。无符号表明首位地址也参与到数据的表示中。

举上述的例子来说,若将字面值0x4B2A2A46赋值给int类型,计算机解析出地址736424 - 736427的内容是1261054534,因为736424的首位为0,其余位的内容是1261054534;若将736424的首位改为1,即0xCB2A2A46,则地址736424~736427的内容是-886429114(补码)。

若将字面值0x4B2A2A46赋值给unsigned int类型,计算机解析出内容依旧是1261054534;若将首位改为1,即0xCB2A2A46,则计算机解析出的内容是3408538182

int a = 0x4B2A2A46;
cout << a << endl;  // 1261054534

int b = 0xCB2A2A46;
cout << b << endl;  // -886429114

unsigned int c = 0x4B2A2A46;
cout << c << endl;  // 1261054534

unsigned int d = 0xCB2A2A46;
cout << d << endl;  // 3408538182
1.1.3 字面值常量

字面值常量(literal) 就是我们写在代码文字中的80、'a’这样。

每个字面值常量也是对应一种数据类型的:

20  // 十进制,int
024 // 八进制,int
0x14  // 十六进制,int

20u  // unsigned int
20l  // long
20ul  // unsigned long
20ll  // long long

3.1415  // 小数表示,double
3.2e-3  // 科学计数法,double

3.14f  // float
3.14l  // long double

'a'  // 字符,char
"hello world"  // 字符串
'\n'  // 转义字符
'\115'  // 字符M

u"hello world"  // Unicode16字符,char16_t
U"hello world"  // Unicode32字符,char32_t
L'a'  // 宽字符,wchar_t
u8"hello world"  // utf-8字符串字面值,char

true  // 布尔类型,bool
false  // 布尔类型,bool

nullptr  // 指针类型字面值,可以转换成任意类型的指针

注意:没有short,布尔类型只有两个。

1.1.4 类型转换

类型转换是C++中比较复杂的一类运算,它分为隐式类型转换显示类型转换

隐式类型转换无须程序员介入,在保证运算对象类型一致不丢失精度的情况下,编译器自动进行。这类转换发生条件众多且情况多样,可以发生在整型内部(整型提升等),也可以发生在整型到浮点型,甚至是整型到自定义类型(转换构造函数)。

显示类型转换是一种程序员可以控制的转换,可以使用如下四种运算符:

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast

上述详细内容请参考【深度C++】之“类型转换”

2. 复合类型

复合类型是指基于其他类型而定义的类型,例如int &ra = a就是基于int类型定义的一个int引用。

2.1 数组

数组(array) 是存放类型相同的对象的容器,通过对象在数组中的位置访问对象。

详细内容,请参考【深度C++】之“数组”

2.2 引用

引用为对象起了另外一个名字,实现了对其他对象的间接访问

int ival = 20;
int &ref_val = ival;  // ref_val引用ival

引用是C++引入的用来简化指针操作的一个类型,它分为左值引用和右值引用。

引用不是一个对象,因此不能定义引用的引用,引用在声明的时候必须初始化,初始化之后不能对其赋值(直接赋值相当于使用被引用对象)、拷贝。

详细内容,请参考【深度C++】之“引用”

2.3 指针

指针是指向另外一种类型的复合类型。与引用类似,也实现了对其他对象的间接访问。

指针不同于引用,是一个对象,因此可以定义指向指针的指针,允许对指针进行拷贝、赋值,声明指针不必初始化,和其他内置类型一样,也存在各种初始化方式。

与指针相关的运算符有

  • 取地址运算符&
  • 解引用运算符*
int ival = 20;
int *p_val = &ival;  // 通过取地址运算符&,定义p_val是指向ival的指针
cout << *p_val << endl;  // 通过解引用运算符*,访问指针的值

详细内容,请参考【深度C++】之“指针”

2.4 const限定符

const限定符可以作用域上述的任何一种数据类型,包括被unsigned修饰或者指针、引用等复合类型。

关于const限定符一共有8类用法,请参考【深度C++】之“const”

3. 自定义数据类型

3.1 结构体

结构体(struct)自定义数据类型的一种方式,与class用法类似,但也有区别。

C++中使用关键字struct来定义一个结构体。

详细内容,请参考【深度C++】之“类与结构体”

3.2 类

类(class) 是面向对象的灵魂,它体现了面向对象抽象和封装的思想,是C++中自定义数据类型的一种方式。

C++中使用关键字class来定义一个类。

详细内容,请参考【深度C++】之“类与结构体”

3.3 联合体

联合体(union) 是一种特殊的类。一个union可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。

详细内容,请参考【深度C++】之“联合体”

3.4 枚举

枚举(enumeration) 使我们可以将一组整型常量组织在一起。和类一样,每个枚举类型定义了一种新的类型。枚举属于字面值常量类型。

枚举包含限定作用域枚举不限定作用于枚举

详细内容,请参考【深度C++】之“枚举”

4. 定义变量

C++中定义变量的规则如下:

类型说明符 声明符列表;
  1. 类型说明符(type specifier):包括基本数据类型(base type)auto类型说明符decltype类型说明符
  2. 声名符 列表:由多个声名符(declarator) 组成,每个声名符由,隔开。每个声名符可以包含类型修饰符。在声名符中定义标识符,并且可以进行初始化。
  3. ;分号结尾

举例:

int a,b = 0;
  1. int类型说明符,是一个基本数据类型
  2. a, b = 0声名符列表,此处包含2个声名符,没有类型修饰符标识符abb使用=初始化为0。
  3. ;分号结尾
int a = 2, *pa, &ra = a;
  1. int类型说明符,是一个基本数据类型
  2. a = 2, *pa, &ra = a声名符列表,此处包含3个声名符,有类型修饰符*&标识符aparaa使用=初始化为2,ra使用=将引用a
  3. ;分号结尾

5. 总结

C++中支持广泛的数据类型,包括基本内置类型自定义数据类型复合类型

基本内置类型包括算数类型空类型算数类型包括整型浮点型

自定义数据类型一共四种:结构体联合体枚举

复合类型包括数组引用指针const限定符

各种类型之间存在着一种普遍支持的运算:类型转换

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值