兼容类型(二)
二、指针类型的兼容性
如果两个指针的类型是兼容类型,应满足以下条件:
- 如果存在类型限定符(例如:const、restrict、volatile。),类型限定符应相同;
- 指针指向兼容类型的对象或者函数。
int *a = NULL; int *b = NULL; int (*c)[5] = NULL; int (*d)[5] = NULL;
指针a、b的类型是兼容类型;指针c、d的类型是兼容类型,指针a、b与指针c、d的类型不兼容。指针a、b都是指向int类型对象的指针;指针c、d都是指向有5个int类型元素的数组的指针。
对于指针,如果存在类型限定符,应注意类型限定符限定的是指针,还是指针指向的对象。以const类型限定符为例,如果类型限定符出现在*号的左边,则是限定指针指向对象的类型,表示指针指向的对象值是不变的;如果类型限定符出现在*号的右边,则是限定指针,表示指针指向的位置是不变的;这两种类型的指针是不兼容的。
int number = 0; const int *a = 0; int * const b = &number; int * volatile c = 0;
指针a表示指向的对象值是不变的;指针b表示指向的内存位置是不变的,即只能指向变量number的地址。指针a与指针b的类型是不兼容的。指针b与指针c的类型也是不兼容的,因为类型限定符不同。
如果存在多个类型限定符,类型限定符的先后顺序不影响类型的兼容性,前提是它们限定的是指针,还是指针指向的对象。
对于使用类型限定符限定的指针,可以使用typedef定义指针的类型,使其意思更清晰,例如:
typedef int *intPtr; ... int a; int b; const intPtr constPtr = &a; constPtr = &b; //非法。
指针变量constPtr等价于int * const constPtr,即指针变量constPtr是使用const类型限定符限定的指针,其指向一个int类型的对象。
三、数组类型的兼容性
如果两个数组类型是兼容类型,应满足以下条件:
- 数组元素类型是兼容类型;
- 数组维数相同;
- 如果两个数组大小说明符都存在,并且都是整数常量表达式,则两个大小说明符应具有相同的常量值;变长数组和其它数组是兼容的。
extern int n; ... { int a[5]; int b[5]; int c[6]; double d[5]; int f[n]; }
数组a、数组b的类型是兼容类型;与数组c的类型不兼容,因为数组大小说明符不相等;数组a、数组b的类型与数组d的类型不兼容,因为数组元素的类型不兼容;数组f的类型与数组a、b、c的类型都是兼容的,因为数组f是变长数组,只要满足数组元素兼容和数组维数相同就可以了;数组f的类型与数组d的类型是不兼容的,因为数组元素的类型不兼容。
int a[20]; int b[4][5]; int c[2][10];
数组a与数组b、数组c的类型不兼容,因为它们的数组维数是不相同的。数组b与数组c的类型不兼容,因为数组大小说明符不相等。
如果存在类型限定符,类型限定符的情况和基本类型相同。
除了作为sizeof运算符的操作数、&运算符的操作数、用于初始化数组的字符串字面量外,数组类型表达式会转换成指针类型表达式,该类型指针指向数组对象的初始元素,并且不是左值(lvalue)。
假设数组arr是一个维数为i×j×...×k的N维数组,如果N=1,arr将转换成指向数组初始元素的指针;如果N≥2,arr将转换成指向维数为j×...×k的N-1维数组的指针。
int *ptr; int (*arrayPtr)[5]; int arrOne[5]; int arrTwo[3][5]; ptr = arrOne; //合法。 arrayPtr = arrTwo; //合法。 arrayPtr = &arrOne; //合法。
ptr与arrOne的类型兼容;arrayPtr、arrTwo与&arrOne的类型兼容。