在c入门中,它告诉我一些遵循的分配规则:
不能将整数数组指针分配给整数指针。
int *pt; int a[3][2];
pt=a; /* invalid */
不能将指向两个整数的数组的指针分配给三个整数的指针。
int (*pt)[3]; int a[3][2];
pt=a; /* invalid */
坦率地说,我对此解释感到困惑。因为尽管上述指针是指向不同对象的指针,但是在内存中,指针都以十六进制地址以无符号形式存储,这意味着它们具有相同的存储形式。它们统一为8位(64位OS)或4位(32位OS)。那么为什么不能从根本上将它们彼此分配呢?因为编译器禁止这类分配?
答案 0 :(得分:4)
语言具有类型的主要原因是为了帮助程序员避免犯错误。指向不同类型事物的指针本身被视为不同类型。诸如此类的规则会遇到许多错误,程序员可能会在其中分配指向错误内容的指针。
int
,两个int
的数组和三个int
的数组是不同类型的事物,因此指向它们的指针是不同类型的指针,并且C要求编译器诊断任何尝试将一个分配给另一个的尝试。 (这可以通过使用强制转换来显式转换指针来覆盖,但是在您了解有关使用不同类型的别名对象的C规则之前,应避免这种情况。)
最简单的是,要设置int *pt
指向int a[3][2]
的第一个元素,可以使用pt = &a[0][0];
或pt = a[0];
。在后者中,由于a
是两个两个int
的三个数组,所以a[0]
是两个int
的一个数组。当在表达式中用作sizeof
或一元&
1 以外的表达式时,它会自动转换为指向其第一个元素的指针,因此其行为与&a[0][0]
。
顺便说一句,语句“…”指针都以无符号形式存储为十六进制地址,这意味着它们具有相同的存储形式。通常将它们统一为8位(64位OS)或4位(32位OS)”。 C标准允许不同类型的指针具有不同的表示形式。这在现代C实现中并不常见,但确实存在。
1 用于初始化字符数组的字符串文字也不会转换为指针。
答案 1 :(得分:1)
类型要点,就像整数,浮点数,字符串等一样。指针算术是根据指向的类型完成的。假设您具有以下指针和对象:
int i;
int *pi = &i
int arr[10];
int (*pa)[10] = &arr;
如果表达式p
的计算结果为i
的地址,那么p + 1
的计算结果为int
之后的下一个i
对象的地址。同样,如果pa
的值为arr
的地址,则pa + 1
的值为{{1}之后的int
的下一个10元素数组的地址} 。
这是数组下标的工作方式-表达式arr
定义为a[i]
-给定起始地址*(a + i)
,偏移量a
对象 (不是字节!),然后取消引用结果。
指向不同类型的指针本身就是不同类型,并且像其他类型一样,不必具有相同的大小和表示形式:
6.2.5类型
...
28指向i
的指针应具有与 指向字符类型的指针。 48)类似地,指向合格或不合格版本的字符的指针。 兼容类型应具有相同的表示和对齐要求。所有 结构类型的指针应具有相同的表示和对齐要求 彼此。所有指向联合类型的指针应具有相同的表示形式,并且 彼此之间的对齐要求。指向其他类型的指针不必相同 表示或对齐要求。
48)相同的表示形式和对齐要求意味着与 函数的参数,函数的返回值以及并集的成员。
在大多数现代台式机和服务器系统(阅读:x86)上,指针类型都具有相同的大小和表示形式,但这是实现的功能,而不是语言。 void
的大小不必与int *
相同。
因此,这就是为什么不能将一种类型的指针分配给另一种的原因,除非它们是兼容类型,或者其中一种是int (*)[3]
,或者使用显式强制转换:
void *
答案 2 :(得分:0)
指针变量int (*pt)[3]
与数组int a[3][2]
不兼容,但指针变量int (*pt)[2]
与数组兼容。
乍看之下,对于新的C程序员,声明int a[3][2];
看起来像是在声明a
为长度为2的数组,其中每个元素都是长度为{{1}的3的数组},但在这种情况下,第一眼便是欺骗。声明int
实际上是将int a[3][2];
声明为长度3的数组,其中每个元素都是a
的长度2的数组。可以用伪英语阅读,其尺寸的标注顺序与声明中出现的尺寸相同,即为“ 将int的array [2]的array [3]声明为int 的array [3]”。在多维数组声明中,“内部”维显示在“外部”维的右侧。
声明int
可以用伪英语理解为“ 将p2声明为指向int的array [2]的指针”,当然int (*p2)[2];
可以读取为“ 将p3声明为int数组[3]的指针”。指针类型是长度不同的数组类型的指针类型彼此不兼容,因此int (*p3)[3];
的类型与p2
的类型不兼容。
在一个表达式(某些类型的表达式除外)中,当多维数组衰减到指向其第一个元素的指针时,它是在衰减过程中消除的第一个维度(最左侧或最外侧的维度),其余所有尺寸(如果有的话)均保留为指向类型。例如,类型为p3
的数组(“” array [A] of array [C] of T “”)将衰减为类型为{{1}的指针}(“ 指向T的array [C]的array [B]的指针”)。
在表达式T [A][B][C]
和T (*)[B][C]
中,p2 = a;
衰减为p3 = a;
类型的a
(“ 指向数组[2]的指针int ”)。该指针类型与&a[0]
的指针类型兼容,但与int (*)[2]
的指针类型不兼容。分配表达式p2
可以,但是分配表达式p3
涉及不兼容指针类型之间的分配。