====== 类型兼容性(Type Compatibility) ======
两个类型兼容(compatible),是指两个类型是同一个类型,或者“足够相近”可当作同一类型看待。由于typedef并没有引入新的类型,所以不影响兼容性的判断。
具体规则如下:
===== 算术类型(Arithmetic) =====
两个算术类型兼容的唯一条件是他们为同一个类型。例如short与short int兼容,但与int、long不兼容。
需要特别注意的是,char、signed char、unsigned char都是不同的类型,因此也不兼容。
此外,类型限定符(type qualifiers)会改变类型,所以const int与int是不同的类型。
===== 枚举类型(Enumeration) =====
枚举类型与具体实现对应的整数类型(integer)相兼容。每个枚举类型的定义都产生一个新类型,所以没有两个枚举类型是兼容的。
例如:
enum E1 {a, b} e1;
enum E2 {c, d} e2;
这里e1与e2的类型是不兼容的。
不过,由于枚举通常被当作整数处理,所以,不同的枚举类型无论兼容与否,也可混合使用。
===== 数组类型(Array) =====
两个数组类型要兼容,首先它们的元素类型要兼容;其次,如果它们的长度都是固定的,则长度必须相等。
例如:
extern int a[];
int b[5];
int c[10];
const int d[10];
int e[n];
其中:
- a与b、c、e都兼容;
- b与a、e兼容;
- c与a、e兼容;
- e与a、b、c兼容;
- d与其他变量都不兼容。
从这些例子可以看到,兼容性不能传递。
===== 指针类型(Pointer) =====
两个指针类型要兼容,首先它们的类型限定符要相似,其次,它们指向的类型要兼容。
===== 函数类型(Function) =====
两个函数类型要兼容,首先它们的返回值类型要兼容;其次:
- 如果他们都有原型(prototype),则参数个数和变参(%%...%%)的使用必须一直,且每个参数的类型必须兼容;
- 如果只有一个函数有原型,则原型的参数列表中不能含变参(%%...%%),并且每个参数的类型必须与该类型按[[.:function_argument_conversions|函数参数转换]]提升后的类型兼容。
===== 结构体/联合类型(Struct/Union) =====
每个结构体/联合类型的定义都产生一个新类型,所以没有两个结构体/联合类型是兼容的。
例如:
struct { int a; int b; } x;
struct { int a; int b; } y;
struct s { int a; int b; } u;
struct s v;
typedef struct s TS;
TS w;
这里x、y、u的类型都是不同的,但u、v、w的类型相同。
{{tag>C语言}}