当前位置: C语言 -- 基础 -- 兼容类型

兼容类型(二)

二、指针类型的兼容性

如果两个指针的类型是兼容类型,应满足以下条件:

如果存在类型限定符(例如:constrestrictvolatile。),类型限定符应相同;

指针指向兼容类型的对象或者函数。

int *a = NULL;
int *b = NULL;
int (*c)[5] = NULL;
int (*d)[5] = NULL;

指针ab的类型是兼容类型;指针cd的类型是兼容类型,指针ab与指针cd的类型不兼容。指针ab都是指向int类型对象的指针;指针cd都是指向有5int类型元素的数组的指针。


对于指针,如果存在类型限定符,应注意类型限定符限定的是指针,还是指针指向的对象。以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的类型与数组abc的类型都是兼容的,因为数组f是变长数组,只要满足数组元素兼容和数组维数相同就可以了;数组f的类型与数组d的类型是不兼容的,因为数组元素的类型不兼容。


int a[20];
int b[4][5];
int c[2][10];

数组a与数组b、数组c的类型不兼容,因为它们的数组维数是不相同的。数组b与数组c的类型不兼容,因为数组大小说明符不相等。

如果存在类型限定符,类型限定符的情况和基本类型相同。


除了作为sizeof运算符的操作数、&运算符的操作数、用于初始化数组的字符串字面量外,数组类型表达式会转换成指针类型表达式,该类型指针指向数组对象的初始元素,并且不是左值(lvalue)。

假设数组arr是一个维数为i×j×...×kN维数组,如果N=1arr将转换成指向数组初始元素的指针;如果N≥2arr将转换成指向维数为j×...×kN-1维数组的指针。

int *ptr;
int (*arrayPtr)[5];
int arrOne[5];
int arrTwo[3][5];

ptr = arrOne;		//合法。
arrayPtr = arrTwo;	//合法。
arrayPtr = &arrOne;	//合法。

ptrarrOne的类型兼容;arrayPtrarrTwo&arrOne的类型兼容。