我只是无法理解以下程序中的错误。我所做的是我已将大小为5的数组的地址分配给(*)[]
类型的指针 ptr 。没有类型不匹配,只要那样就可以了。但是我想要打印值 ptr + 1 。正如我所料,它显示了一个关于未指定边界的错误。但它只是错过了当我将它ptr+1
转换为void*
时,ptr+1
如何正常工作。
投射很好,但在此之前,程序如何计算(void*)ptr+1
,因为它根本不知道边界?它如何知道是向前移动5个元素,还是向前移动8个元素或向前移动任何元素?为什么ptr+1
不会显示与ctr
相同的错误?
为了更好地突出整个事情,我还使用了一个指针(*)[5]
,它明确声明为(*)[]
类型,而不是#include<stdio.h>
int main(void)
{
int ar1[5]={1,5,3,8,9};
int (*ptr)[]=&ar1,(*ctr)[5]=&ar1;
printf("%p\n",ptr+1); //ERROR about unspecified bounds
printf("%p\n",(void*)ptr+1); //It's ok
printf("%p\n",ctr+1); //It's ok
}
。请告诉我这背后的技术原因。谢谢。
printf()
PSST !! 最后两个正确的printf("%p\n",ptr+1);
s不会产生相同的值。如果我注释掉了不正确的PSST!!
行,那么这就是输出。< / p>
0023FF25
0023FF38
ptr+1
我再次检查了它,在(void*)ptr+1
的{{1}}部分,1
被简单地添加到ptr
的数值。什么是继续?
答案 0 :(得分:1)
根据您的代码
int (*ptr)[]
ptr是一个指向UNKNOWN size数组的指针。到目前为止,编译器不知道ptr指向的大小。当你试图增加时,编译器仍然不知道要增加多少。 指针增量将是sizeof(指向元素)的补充。所以你得到错误“未指定的绑定”。
现在,对于你剩下的两个问题,为了更好地理解,请允许我在一个问题上重新解释你的两个问题。 “为什么(VOID *)有点像(CHAR *)”??(那是那个:)?) 你的答案是
在C标准(N1256草案)中:6.2.5-27:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
答案 1 :(得分:0)
请告诉我背后的技术原因。
技术原因是当添加一个时,编译器会尝试跳转到该类型的下一个实例。
示例:向int
指针添加一个将增加 4 ,因为int
长度为4个字节,然后指向下一个int。
在您的示例中,使用ptr,您从未指定大小。跳转到下一个元素是不可能的,因为这个元素的大小是未知的。一旦你通过指向一个正好包含5个元素的数组来指定大小,它就会再次起作用。
当将ptr转换为void时,再次转到下一个元素变得容易了。编译器只添加了一个字节。
在你的跑步中:
ptr
是0023FF24
((void*)ptr) + 1
是0023FF25
(基地址加上“void”的一个元素的1个字节)
ctr
是0023FF24
(与ptr相同)
ctr + 1
是0023FF38
(基地址,加上sizeof(int)
的一个元素的20( 5 * int (*)[5]
)个字节