其他数据类型
定义数据类型 (typedef)
C++ 允许我们基于其他现有的数据类型定义自己的类型。我们可以使用关键字
typedef来实现,其格式为:
typedef existing_type new_type_name;
,其中
existing_type是 C++ 的基本或复合类型,而
new_type_name是我们定义的新类型的名称。例如:
1 2 3 4
|
typedef char C;
typedef unsigned int WORD;
typedef char * pChar;
typedef char field [50];
|
在此示例中,我们定义了四个数据类型:
C,
WORD,
pChar和
字段为
char,
unsigned int,
char*和
char[50]分别,这些类型可以像任何其他有效类型一样用于后续的声明。
1 2 3 4
|
C mychar, anotherchar, *ptc1;
WORD myword;
pChar ptc2;
field name;
|
typedef并不会创建不同的类型。它仅仅是创建现有类型的别名。这意味着变量
myword的类型可以被认为是
WORD或者
unsigned int,因为它们实际上是相同的类型。
typedef定义一个程序中频繁使用的类型的别名会非常有用。当程序后续版本可能需要更改类型时,或者当您想使用的类型名称太长或令人困惑时,定义类型也很有用。
联合体 (Unions)
联合体允许同一块内存区域被访问为不同的数据类型,因为它们实际上都位于同一内存地址。其声明和使用方式与结构体类似,但功能完全不同。
union union_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;
联合体
联合体声明的所有成员都占据相同的物理内存空间。其大小等于声明中最大成员的大小。例如:
1 2 3 4 5
|
union mytypes_t {
char c;
int i;
float f;
} mytypes;
|
定义了三个成员,
1 2 3
|
mytypes.c
mytypes.i
mytypes.
|
每个成员都有不同的数据类型。由于它们都指向同一内存位置,修改其中一个成员的值会影响所有成员的值。我们无法独立地在它们中存储不同的值。
联合体的一个用途是将一个基本类型与一个较小元素的数组或结构体组合起来。例如:
1 2 3 4 5 6 7 8
|
union mix_t {
long l;
struct {
short hi;
short lo;
} s;
char c[4];
} mix;
|
定义了三个名称,允许我们访问相同的 4 字节组:
mix.l,
mix.s和
mix.c根据我们想要访问这些字节的方式,可以将其视为一个单独的
long类型数据,或者两个
short元素,或者一个
char元素数组,分别对应。我在联合体中混合了类型、数组和结构体,以便您可以看到访问数据的不同方式。对于一个“小端序”(大多数 PC 平台)系统,该联合体可以表示为:
联合体成员的確切对齐方式和顺序是平台相关的。因此,要注意这种用法可能存在的移植性问题。
匿名联合体
在 C++ 中,我们可以选择声明匿名联合体。如果我们声明一个没有名称的联合体,该联合体将是匿名的,并且我们可以直接通过其成员名称访问其成员。例如,看看这两个结构体声明之间的区别:
带有常规联合体的结构体 | 带有匿名联合体的结构体 |
struct {
char title[50];
char author[50];
union {
float dollars;
int yen;
} price;
} book;
| struct {
char title[50];
char author[50];
union {
float dollars;
int yen;
};
} book;
|
这两段代码之间的唯一区别在于,第一段代码中我们给联合体起了一个名称(
price),而在第二段代码中我们没有。当访问对象的成员
dollars和
和yen
1 2
|
book.price.dollars
book.price.
|
时,区别就显现出来了。对于第一个类型的对象,访问方式是:
而对于第二个类型的对象,访问方式是:
dollars和
和再次提醒您,由于这是一个联合体而不是结构体,成员
price占据相同的物理内存空间,因此它们不能同时用于存储两个不同的值。您可以为
设置美元值或日元值,但不能同时设置两者。
枚举 (enum)
enum enumeration_name {
value1,
value2,
value3,
.
.
} object_names;
枚举创建新的数据类型来包含不同于基本数据类型可能值的特定值。其形式如下:
例如,我们可以创建一个名为colors_t
1
|
enum colors_t {black, blue, green, cyan, red, purple, yellow, white};
|
的新变量类型来存储颜色,使用以下声明:
请注意,我们没有在声明中包含任何基本数据类型。可以说,我们是从零开始创建了一个全新的数据类型,而没有基于任何其他现有类型。这种新类型变量可能取的可能值是包含在大括号内的新常量值。例如,在声明了枚举之后,以下表达式将是有效的:
例如,我们可以创建一个名为枚举与数值变量是类型兼容的,因此其常量在内部总是被赋予一个整数数值。如果未指定,则第一个可能值的整数等价物是
1 2 3 4
|
colors_t mycolor;
mycolor = blue;
if (mycolor == green) mycolor = red;
|
,后续值按 +1 递增。因此,在我们上面定义的
0数据类型中,
例如,我们可以创建一个名为black
将等价于blue
0,
greenblue
1,
,依此类推。为
2我们可以显式指定枚举类型所能取的任何常量值的整数值。如果其后的常量值未被赋予整数值,则自动假定为前一个值加一。例如:
在这种情况下,枚举类型
1 2 3
|
enum months_t { january=1, february, march, april,
may, june, july, august,
september, october, november, december} y2k;
|
months_t
的变量y2k
可以包含 12 个可能值中的任何一个,这些值从january
到为
december,它们等价于值介于
1和
12(不是介于
0和
11,因为我们已经将
到设置为等于
1).