1. 原始类型
C++ 中的原始类型包括整型(integral types)、浮点型(floating-point types)、字符型(character types)、布尔型(boolean types)以及空指针类型(nullptr_t)。
(1)整型
整型是 C++ 中最基本的类型之一,可以分为带符号(signed)和无符号(unsigned)两种类型。主要的整型类型包括:
char
:1 字节,用于存储字符或者小整数,带符号类型。
short
:2 字节,用于存储比 char 大但比 int 小的整数,带符号类型。
int
:通常为 4 字节,用于存储正负整数,带符号类型。
long
:通常为 8 字节,用于存储比 int 大的整数,带符号类型。
long long
:通常为 8 字节,用于存储更大的整数,带符号类型。
以上整型类型还可以加上 unsigned
修饰符,表示无符号类型。
(2)浮点型
浮点型用于存储实数。主要的浮点型类型包括:
float
:4 字节,单精度浮点数。
double
:8 字节,双精度浮点数。
long double
:通常为 16 字节,更高精度的浮点数。
(3)字符型
字符型用于存储字符。C++ 中的字符型有两种类型:
char
:1 字节,用于存储 ASCII 码或者扩展 ASCII 码字符。
wchar_t
:2 或 4 字节(根据编译器而定),用于存储 Unicode 字符。
(4)布尔型
布尔型用于存储真(true
)假(false
)值,布尔型只占用一个字节的空间。
(5)空指针类型
空指针类型是 C++11 新增的类型,用于表示空指针,只有一个取值,即 nullptr
。
2. 复合类型
C++ 中复合类型是由原始类型定义的,包括:指针、数组、结构体和联合等。
(1)指针
指针是一个变量,其值为另一个变量的地址。指针可以指向任何数据类型(包括原始类型和复合类型)。在 C++ 中,我们使用 * 运算符来声明指向某一类型的指针。如:
int var = 10; int *ptr; ptr = &var;
上述代码,ptr 是一个指向 int 类型变量 var 的指针。
(2)数组
数组是一种存储相同数据类型元素的集合。C++ 中使用 []
运算符来定义数组。例如:
int arr[5] = {1, 2, 3, 4, 5};
上述代码定义了一个由 5 个 int 类型元素组成的数组,可以通过下标来访问数组元素。例如:arr[0]
表示数组的第一个元素。
(3)结构体
结构体是一种自定义的数据类型,可由多个不同类型的数据成员组成。在 C++ 中,使用 struct
关键字来定义结构体。例如:
struct Person { char name[20]; int age; float height; };
上述代码定义了一个名为 Person 的结构体,其包含三个数据成员:name、age 和 height。我们可以通过 . 运算符来访问结构体的数据成员。例如:
Person p; strcpy(p.name, "张三"); p.age = 18; p.height = 1.75;
上述代码创建了一个 Person 类型的变量 p,并设置了它的 name、age 和 height 数据成员。
(4)联合
联合是一种特殊的结构体,它的所有数据成员共享同一块内存空间, C++ 中使用 union
关键字来定义联合。例如:
union Number { int i; float f; };
上述代码定义了一个名为 Number 的联合,其包含两个数据成员:i 和 f。i 和 f 共享同一块内存空间。我们可以通过 . 运算符来访问联合的数据成员。例如:
Number n; n.i = 10; cout << n.f << endl; // 输出 2.31584e-41 n.f = 3.14; cout << n.i << endl; // 输出 1078523331
上述代码创建了一个 Number 类型的变量 n,并设置了它的 i 和 f 数据成员。由于 i 和 f 共享同一块内存空间,因此改变其中一个数据成员的值会影响另一个数据成员的值。
(5)枚举类型
枚举类型是一种自定义的数据类型,用于表示某些有限的离散值,C++ 中使用 enum
关键字来定义枚举类型。例如:
enum Color { RED, GREEN, BLUE };
上述代码定义了一个名为 Color 的枚举类型,其包含三个值:RED、GREEN 和 BLUE。枚举类型的值默认从 0 开始自增。可使用枚举值来定义变量。例如:
Color c = BLUE;
上述代码定义了一个名为 c 的 Color 类型的变量,并将其设置为 BLUE。
3. 类型转换
3.1 隐式类型转换
(1)整型提升
在表达式运算中,较小的整型类型(如 char
、short
)会被自动转换为更大的整型类型(如 int
、long
)。例如:
char c = 'A'; int i = c + 10;
上述代码字符变量 c 被提升为 int
类型,以便与整数常量 10 相加。
(2)浮点型提升
当一个浮点数参与运算时,如果其它操作数不是浮点数,则其它操作数将被转换为浮点数。例如:
float f = 3.14; double d = f + 1.0;
上述代码单精度浮点数 f 被隐式转换为双精度浮点数,以便与双精度浮点数常量 1.0 相加。
(3)向下转换
当一种数据类型的取值范围小于另一种数据类型时,较大的数据类型可以被自动转换为较小的数据类型。这种转换称为向下转换,通常需要显式地告诉编译器进行该操作。例如:
int i = 10; char c = i;
上述代码整数变量 i 被强制转换为 char
类型,并且只保留了低 8 位。
3.2 显式类型转换
C++ 中提供了四种显式类型转换方式:static_cast
、dynamic_cast
、reinterpret_cast
和 const_cast
。
(1)static_cast
static_cast
可以用于基本数据类型之间的转换,例如:
int i = 10; float f = static_cast<float>(i);
上述代码将整型变量 i 转换为浮点型变量 f。
static_cast
还可以用于指针之间的转换,例如:
int *ptr = new int(10); void *vp = static_cast<void*>(ptr);
上述代码将 int 类型指针 ptr 转换为 void* 类型指针 vp。
(2)dynamic_cast
dynamic_cast
主要用于类层次结构中,用于安全地将基类指针转换为派生类指针,或将派生类指针转换为基类指针。例如:
class Base {...}; class Derived : public Base {...}; Base *bp = new Derived; Derived *dp = dynamic_cast<Derived*>(bp);
上述代码中,基类指针 bp 被转换为派生类指针 dp。
(3)reinterpret_cast
reinterpret_cast
可以将一种指针类型转换为另一种指针类型,或者将整数类型转换为指针类型。使用该方式进行转换时需要特别小心,因为它可以忽略类型之间的任何差异和安全检查。例如:
int i = 10; char *cp = reinterpret_cast<char*>(&i);
上述代码将整型变量 i 的地址强制转换为 char* 类型指针。
(4)const_cast
const_cast 主要用于去除对象的常量性。例如:
const int ci = 10; int *ip = const_cast<int*>(&ci); *ip = 20; // 此操作会导致未定义行为
上述代码中,常量对象 ci 被强制转换为非常量对象,并且该操作可能会导致未定义行为。
4. 总结(手稿版)
20年前学习C++语言的幼稚记录