项目 | 描述 |
---|---|
搜索引擎 | Bing、Google |
AI 大模型 | 文心一言、通义千问、讯飞星火认知大模型、ChatGPT |
菜鸟教程 | 数据类型 |
C++ Primer Plus (第六版)中文版 | 史蒂芬·普拉达 / 张海龙,袁国忠 译 |
精通C++(第九版) | ISBN:9787302503163 |
黑马程序员 | C++ |
CPlusPlus | Reference |
项目 | 描述 |
---|---|
操作系统 | Windows 10 专业版 |
编辑器 | VSCode |
编译器 | g++.exe (x86_64-win32-seh-rev1, Built by MinGW-Builds project) 13.1.0 |
数据类型用于确定变量存储的 数据所占用的内存空间大小和支持的操作
。数据类型分为基本数据类型和复合数据类型两大类。
基本数据类型
基本数据类型是编程语言中的原始数据类型,通常由编程语言提供,用于存储 单一的
、简单的
数据值。
复合数据类型
复合数据类型用于 组合多个基本数据类型或其他复合数据类型
,以创建更为复杂的数据结构。复合数据类型使程序能够组织和操作多个不同的数据元素。
数据类型在 C++
中是 静态类型
,这意味着 在变量声明时必须指定其数据类型
,编译器在编译时会检查 类型一致性
,从而提高了代码的稳定性和安全性。选择适当的数据类型对于编写 高效、可读性强
的代码非常重要,因为它会影响变量的内存空间占用、运行速度以及程序的正确性。
C++ 中的整型数据类型用于存储整数值,这些值可以是 正数
、负数
或 零
。整型数据类型可以分为 两大类
,即有符号整型数据类型与无符号整型数据类型。
有符号整型数据类型能够用于存储 正数
、负数
和 零
。如果您需要存储的整型数据需要使用到 负数
,那么请使用有符号整型数据类型。
项目 | 大小 | 范围 | 数量级 |
---|---|---|---|
short、signed short、short int 、signed short int | 两个字节 | -32,728 ~ 32,727 |
万 |
int、signed | 四个字节 | -2,147,483,648 ~ 2,147,483,647 |
十亿 |
long、signed long、long int、signed long int | Windows 占用四个字节;Linux 的 32 位 系统占用四个字节,64 位 系统占用八个字节 |
-2,147,483,648 ~ 2,147,483,647 |
十亿 |
long long、signed long long、long long int、singned long long int | 八个字节 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
百亿亿 |
注:
有符号整型数据类型中的各个 子类型
均存在 多个名称
,您可以使用某一子类型中的某一名称来表示该子类型。
无符号整型数据类型用于存储 正数
与 零
。如果您需要存储的整型数据不需要使用到 负数
,那么请您使用无符号整型数据类型。
项目 | 大小 | 范围 | 数量级 |
---|---|---|---|
unsigned short、unsigned short int | 两个字节 | 0 ~ 65,535 |
万 |
unsigned、unsigned int | 四个字节 | 0 ~ 4,294,967,295 |
十亿 |
unsigned long、unsigned long int | Windows 占用四个字节;Linux 的 32 位 系统占用四个字节,64 位 系统占用八个字节 |
0 ~ 4,294,967,295 |
十亿 |
unsigned long long、unsigned long long int | 八个字节 | 0 ~ 18,446,744,073,709,551,615 |
千亿亿 |
有符号整型数据类型 需要使用一个二进制位作为符号位
,符号位用于
表示该整型数值是负数还是非负数。无符号整型数据类型仅用于表示 非负数
,故不需要使用到符号位。因此,同样位数的无符号整数具有 更大的正数表示范围
,但它不能用于表示负数。
在不同的 C++
实现中,不同的数据类型所占用的内存空间是不同的,这可能会导致混乱。C++
提供了一种灵活的标准,该标准确保了不同数据类型所占用的最小内存空间:
short
数据类型所占据的内存空间至少为 两个字节
。int
至少与 short
数据类型所占据的内存空间相同。long
数据类型所占据的内存空间至少为 四个字节
,且至少与 int
数据类型所占据的内存空间相同。long long
数据类型至少为 八个字节
,且至少与 long
数据类型所占据的内存空间相同。不同数据类型所占用内存空间的实际大小可能会因不同的系统和编译器而异
。如果您需要计算在您所使用的环境中,各数据类型实际占用的内存空间大小是多少?那么您可以考虑考虑 sizeof
运算符。
sizeof
运算符是C++中用于 确定变量或数据类型占用的内存空间大小
的运算符 (以字节为单位,一字节包含八个二进制位)
。你可以通过编写简单的代码来确定在你的系统上各种数据类型所占用的空间大小。对此,请参考如下示例:
// 导入 C++ 头文件 iostream 以实现对流的处理
#include
// 使用标准命名空间
using namespace std;
int main () {
cout << "Short Int\t" << sizeof(short) << endl;
cout << "Int\t\t" << sizeof(int) << endl;
cout << "Long Int\t" << sizeof(long) << endl;
cout << "Long Long Int\t" << sizeof(long long) << endl;
// 确保程序执行完毕后不会退出
system("pause");
return 0;
}
执行结果
Short Int 2
Int 4
Long Int 4
Long Long Int 8
请按任意键继续. . .
注:
sizeof
是 C++ 中提供的运算符,用 括号将操作数包裹的操作并不是必须的
。但在 sizeof 运算符的操作对象为 数据类型
时,则必须将其进行包裹。否则,C++ 将抛出异常。
C++
允许您使用四种种方式来表示整数。具体如下:
0
为前缀 ,则该整数将被视为 八进制
数值。0X
或 0x
为前缀,则该整数将被视为 十六进制
数值。0B
或 0b
为前缀,则该整数将被视为 二进制
数值。举个栗子
#include
using namespace std;
int main () {
// 十进制数值
cout << 66 << endl;
// 十六进制数值
cout << 0X66 << endl;
cout << 0X2F << endl;
// 八进制数值
cout << 066 << endl;
// 二进制数值
cout << 0b1001 << endl;
system("pause");
return 0;
}
执行结果
66
102
47
54
9
请按任意键继续. . .
注:
0 ~ 7
范围中的数值。例如 0982
就是一个错误的八进制数值。0 ~ 9
及 a ~ f
或 A ~ F
范围中的数值。例如,0X89D
就是一个错误的十六进制数值。0 ~ 9
范围中的数值。例如,10a
就是一个错误的十进制数值。在使用 cout
将数值输出至终端中时,其他进制的数值都将被转化为十进制数值后输出。
如果您希望 cout
将数值转换为指定进制的数值后在执行窗口中输出,那么你可以使用 hex
、dec
及 oct
关键字用以将数值分别转换为十六进制、十进制及八进制数值后在执行窗口中输出。
举个栗子
#include
using namespace std;
int main () {
// 将十进制数值转化为十六进制后输出至终端中
cout << hex << 36 << endl;
// 将十进制数值转化为八进制数值后输出至终端中
cout << oct << 36 << endl;
// 将十进制数值原样输出
cout << dec << 36 << endl;
system("pause");
return 0;
}
执行效果
24
44
36
请按任意键继续. . .
C++ 提供 oct
与 hex
关键字来将十进制数值转化为指定进制数值后进行输出我们都能够理解,可为什么还需要提供 dec
关键字来将十进制数值以十进制格式进行输出呢?这不是 cout
的默认行为吗?
原来,在 cout
语句中使用 dec
、oct
及 hex
关键字后,后续的 cout
语句都将被影响,而使用 dec
关键字则能够使得 cout
恢复默认行为。对此,请参考如下示例:
#include
using namespace std;
int main () {
// 在下述 cout 语句中,实际发挥作用的是 hex 而不是 oct 关键字。
// 因此,后续 cout 语句都将被 hex 关键字影响。
cout << oct << hex << 15 << endl;
cout << 15 << endl;
// 通过 dec 关键字恢复 cout 的默认行为
cout << dec;
cout << 15 << endl;
system("pause");
return 0;
}
执行效果
f
f
15
请按任意键继续. . .
C++ 标准库没有直接提供用于 cout
的二进制输出控制符,但您可以编写一个函数或使用其他方法将整数转换为二进制字符串,然后通过 cout
进行输出。
字面量是在程序中 直接使用的数据值
,而 不需要任何计算或存储操作
。字面量可以是整数、浮点数、字符、字符串或其他数据类型的常数值。
42 // 整数字面量
3.14 // 浮点数字面量
'A' // 字符字面量
"Hello, World!" // 字符串
在 C++
中,并不是只有变量有其数据类型,字面量也是有其所属的数据类型的。整型字面量使用的默认数据类型为 signed int
,我们可以通过如下代码进行验证。
#include
using namespace std;
int main(){
cout << sizeof 12 << endl;
// usigned int 类型所能够表示的最大数值为 4,294,967,295
cout << sizeof 4294967295 << endl;
system("pause");
}
执行结果
sizeof
运算符的结果为 4
表明操作数所属的数据类型为 signed int
或 unsigned int
,那么究竟哪个才是 C++ 默认使用的数据类型呢?
为此,我们将 sizeof
的操作数设置为 4294967295
,这个数值是无符号 int
类型所能够表示的最大数值。sizeof 4294967295
的输出结果为 8
,则表明该整型字面量使用的不是 int
数据类型。故准确来说,整型字面量数据默认使用的数据类型是 signed int
。
4
8
请按任意键继续. . .
注:
在字面量数值的大小超出了 int
所能表示的范围时,C++ 将从其它整型数据类型中选择 尽可能小(C++ 并不因此为整型字面量使用无符号数据类型)且合适
的数据类型作为该整型字面量的数据类型。
除了让 C++
为整型字面量分配合适的数据类型外,我们也可以 通过在字面量中添加后缀来指定该字面量使用的数据类型
。C++ 支持的整型数据类型的后缀有:
项目 | 后缀 |
---|---|
long | l 、L |
unsigned long | ul (u 及 l 的顺序可以发生变换且两者的大小写形式不被限制) |
long long | ll 、LL |
unsigned long long | ull 、Ull 、uLL 、ULL |
无符号整型数据类型 | u 、U |
举个栗子
#include
using namespace std;
int main() {
// 4294967295 是 unsigned int 所能够表示的最大数值
cout << sizeof 4294967295U << endl;
// 4294967296U 由于超出了 unsigned int
// 所能够表示的最大数值,故使用 usigned long long
cout << sizeof 4294967296U << endl;
// 在不添加 u 或 U 后缀时,C++ 默认为这些
// 字面量使用有符号整型数据类型。
cout << sizeof 4294967295 << endl;
system("pause");
return 0;
}
执行效果
4
8
8
请按任意键继续. . .
在 C++ 中,即使整型字面量的取值范围在 short
类型所支持的范围之内,该字面量也将使用 signed int
而不是 signed short
作为该字面量的数据类型。并且,C++ 中也没有为整型数据类型 short
提供相应的后缀。但我们可以通过 static_cast
进行不同数据类型之间的转化。对此,请参考如下示例:
#include
using namespace std;
int main() {
cout << sizeof 1 << endl;
// 通过 static_cast 将字面量的数据类型转化为 short
cout << sizeof static_cast<short>(1) << endl;
system("pause");
return 0;
}
执行效果
4
2
请按任意键继续. . .
在某一数据类型的数据 超出了该数据类型所支持的范围时
,变量值将 跳转到范围的另一端并在此基础上继续计算
。对于整型数据类型而言,可能发生如下情况:
有符号整型溢出
以 int
类型举例。当 int
类型的整型数值 增加到其上限并继续增加时
,它可能会变为 该类型所支持的最小值并以此为基础继续进行计数
。当 int
类型的整型数值 减少到其下限并继续减少时
,它可能会变为 该类型所支持的最大值并以此为基础继续进行计数
。
无符号整型溢出
当无符号整型数值增加到其所属的数据类型所支持的上限并继续增加时
,它会 回绕到数值 0
,并 以此为基础继续进行计数
。当其值减少到 0
并继续减少时,它会回绕到该类型的最大值。
举个栗子
#include
using namespace std;
int main() {
// signed short 数据类型所支持的最大值
short span_max = 32767;
// unsigned short 数据类型所支持的最小值
short span_min = -32768;
span_max += 7;
span_min -= 10;
cout << span_max << endl;
cout << span_min << endl;
system("pause");
return 0;
}
执行结果
-32762
32758
请按任意键继续. . .
ANSI/ISO C++
标准开始支持 布尔类型
。布尔
这个名称来源于英国数学家 George Boole
,是他开发了逻辑率的数学表示法。在计算中,布尔变量的值可以是 true
或 false
,分别代表了 真
与 假
。
拓展
C99
之前,C语言
的标准没有提供布尔类型,但是这不意味着 C 语言不能表示布尔值的概念。C 中的所有 布尔运算符(&&、|| 等)
以及条件语句(if、While 等)
都以非零值代表真,零值代表假。C++ 支持布尔类型前
,C++
同 C
一般,将 0
解释为 false
,将 非 0 值
解释为 true
。但在 C++
支持布尔类型后,你也仍可以使用 0
来代替 false
或是使用 非 0 值
来代替 true
在条件语句发挥作用。在 C++ 中,关键字 true
及 false
分别可以看作是存储了 1
及 0
的变量。
举个栗子
#include
using namespace std;
int main() {
cout << true << endl;
cout << false << endl;
system("pause");
return 0;
}
执行结果
1
0
请按任意键继续. . .
布尔类型通常作为 判断一个表达式是否正确的结果
,若表达式正确则布尔运算的结果为 true
,若表达式错误则布尔运算的结果为 false
。
举个栗子
#include
using namespace std;
int main() {
bool result = 3 < 1;
// 括号用于提升表达式的优先级,
// 防止 C++ 被迷惑导致异常产生。
cout << (3 > 1) << endl;
cout << result << endl;
system("pause");
return 0;
}
执行结果
1
0
请按任意键继续. . .
在 C++
中,字符型变量用于存储字符。您可以使用 char
关键字声明一个字符型变量,使用 char
关键字创建的变量将占用一个字节的内存空间。
注:
\n
、\t
。ASCII(American Standard Code for Information Interchange)
是一种字符编码标准,用于 将文本字符映射到数值
。ASCII
最早在计算机领域中广泛使用,它定义了 128
个不同的字符,包括 控制字符(如换行和回车)
以及 可打印字符(如字母、数字、标点符号等)
。ASCII 定义的每个字符都被分配了一个 唯一的整数值
,范围从 0
到 127
。
注:
世界上存在许多的编码方案,但这些方案大多是 基于 ASCII 编码进行扩展的
,因此 ASCII
编码也被认为是 字符编码的基础
。
在 C++
中,使用 char
类型的变量存储某一字符时,存储的不是字符本身而是该字符对应的 ASCII 编码值
。我们可以通过如下代码对此进行验证:
#include
using namespace std;
int main() {
char letter = 'a';
cout << letter << endl;
cout << letter + 1 << endl;
system("pause");
return 0;
}
执行效果
a
98
请按任意键继续. . .
上述示例的执行结果表明了如下两点事实:
letter
字符类型的变量中的数据 能够与数值进行运算
。cout
将字符类型的变量所存储的值输出至终端中显示的 的确是字符而不是数值
。对于上述两点事实分别作出如下两点解释:
cout
在将字符类型的变量所存储的值 输出至终端前
会将变量值转化为 该值所对应的 ASCII 字符
。除了传递字符给 char
变量外,你还可以 直接将需要保存的字符对应的 ASCII 码传递给该变量作为该变量的值
。例如:
#include
using namespace std;
int main() {
char letter = 97;
cout << letter << endl;
system("pause");
return 0;
}
执行结果
a
请按任意键继续. . .
char
在默认情况下是否为有符号数据类型由 C++ 实现来决定,这样编译器的开发人员将能够最大限度地将这种类型与硬件属性匹配起来。你可以使用 signed char
或 unsigned char
来显式指定 char
为哪一种类型。
如果将 char
用作数值类型,则 unsigned char
与 signed char
之间的差异将变得非常重要。unsigned char
类型所支持的范围为 0 ~ 255
,而 signed char
类型所支持的范围为 -128 ~ 127
。
举个栗子
#include
using namespace std;
int main() {
unsigned char letter = 130;
cout << letter << endl;
cout << "--------------------" << endl;
cout << (int)letter << endl;
system("pause");
return 0;
}
执行效果
为了使 cout
语句 直接输出字符类型变量所存储的具体数
值,在上述示例中我们通过使用 (int)
将字符类型的数据转化为整型数据类型。
--------------------
130
请按任意键继续. . .
请尽可能使用 unsigned char
或 signed char
来显式指定 char
的类型,否则您无法判断运行程序后是否会出现如下状况:
#include
using namespace std;
int main() {
char letter = 130;
cout << letter << endl;
cout << "--------------------" << endl;
cout << (int)letter << endl;
system("pause");
return 0;
}
执行结果
--------------------
-126
请按任意键继续. . .
C++ 不允许使用空字符型字面量
。在需要字符型字面量时,确保使用 单引号包裹一个字符
以避免编译时错误。对此,请参考如下示例:
#include
using namespace std;
int main() {
// 尝试向终端输出空字符型字面量
cout << '' << endl;
system("pause");
return 0;
}
执行效果
C++ 编译器抛出异常信息 empty character constant
。