对于(* ptr)[],为什么printf(“%p”,(void *)ptr + 1)工作但不是printf(“%p”,ptr + 1)?

时间:2013-05-02 10:36:39

标签: c pointers casting indexoutofboundsexception

我只是无法理解以下程序中的错误。我所做的是我已将大小为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的数值。什么是继续?

2 个答案:

答案 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时,再次转到下一个元素变得容易了。编译器只添加了一个字节。

在你的跑步中:

ptr0023FF24

((void*)ptr) + 10023FF25(基地址加上“void”的一个元素的1个字节)

ctr0023FF24(与ptr相同)​​

ctr + 10023FF38(基地址,加上sizeof(int)的一个元素的20( 5 * int (*)[5])个字节