2013-05-02 86 views
1

我只是不明白在下面的程序中的错误。我做了什么是我已经分配了一个大小为5的数组地址到指针ptr类型(*)[]。没有类型不匹配,它可以作为尽管如此。但是我想打印值ptr + 1。正如我所料,它显示了一个关于未指定边界的错误。但它只是想我如何将相同的ptr+1工作正常,当我把它投入void*对于(* ptr)[],为什么printf(“%p”,(void *)ptr + 1)有效但不是printf(“%p”,ptr + 1)?

铸造是好的,但在它之前,该程序如何计算ptr+1,因为它根本不知道边界?如何知道是否要提前5个元素,或者前面8个元素或前面的任何元素?为什么(void*)ptr+1显示与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 
} 

PSST !!最后两个正确printf() s不会产生相同的值。如果我注释掉不正确的printf("%p\n",ptr+1);行,则这是输出。

0023FF25

0023FF38

PSST!!我检查一遍,INT的(void*)ptr+1ptr+1部分,一个1只是简单地添加到ptr数值。什么事?

+0

@KingsIndian MinGW的 – Thokchom 2013-05-02 11:22:20

回答

0

请给我这背后的技术原因。

技术上的原因是,当添加一个时,编译器会尝试跳转到该类型的下一个实例。

实施例:将一种给int指针将由因为int是4个字节长递增,然后,将指向下一个INT。

在你的例子中,用ptr你永远不会指定大小。跳到下一个元素是不可能的,因为这个元素的大小是未知的。一旦你通过指向一个正好5个元素的数组来指定大小,它就会再次运行。

当将ptr转换为void时,再次转到下一个元素变得很容易。编译器只添加了一个字节。

在跑步:

ptr0023FF24

((void*)ptr) + 10023FF25(基地址加用于一个元件1个字节的 “空隙”)

ctr0023FF24(同PTR)

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

+0

因此,在32位系统中,如果我们将1加1到一个整数指针,它会跳转4个地方,但是当增加时,void指针跳过1个地方/再见? – Thokchom 2013-05-02 10:59:40

+0

正确。任何指针算术乘以sizeof(type指向)''与'void'是特殊的,因为它没有大小,但被视为大小1。所以'int * x; x + = 2;'将x的值提前8(int的两倍大小)。 'void * x; x + = 2;'将x的值提前2(两倍1)。 – nvoigt 2013-05-02 11:03:02

+2

@ Thokchom标准中不允许指针'void *'的算术运算。一些编译器,如gcc,允许它作为扩展。我不知道有一种编译器在指针算术中处理与'char *'不同的'void *',如果它允许对'void *'进行算术运算,但不应该依赖它。 – 2013-05-02 11:35:07

-1

你在这里进行什么奇怪的声明...也许你正试图做到这一点:

int *ptr=ar1; 

请记住,创建一个数组你,其实时,定义一个指针指向第一个数组元素,然后保留足够的内存以包含整个数组。所以,在

int ar1[5] = {1,5,3,8,9}; 

你已经在内存中保留余地5点的整数,它们初始化为给定的一组值,并定义为AR1指针的第一个元素。

索引数组时,您正在对数组指针应用偏移量。您将访问指针+(size_of(element)* index)内存位置。

如果您在变量声明中使用[],仅仅是与使用*,所以有

int *myvar[]; 

是一样的有

int **myvar; 

所以,当你正在申报此

int (*ptr)[]=&ar1 

你实际上定义一个指针的指针,并与的地址对其进行初始化指向你的数组的指针。确实很奇怪。所以,回到我最初的建议,啥子你正在寻找的也许是

int *ptr=ar1; 
+0

有什么错我的声明。 'ar1'和'ar1'一样有意义。 – Thokchom 2013-05-02 10:54:15

+0

也检查[this](http://stackoverflow.com/questions/859634/c-pointer-to-array-array-of-pointers-disambiguation) – 2013-05-02 11:00:59

+2

“如果在变量声明中使用'[]',就像使用'*'“一样。对于函数参数,它们是相同的,但不是在普通的变量声明中。 'int * myvar [];'声明指向int的指针的数组(未知大小),'int ** myvar;'声明指向int的指针。这些是完全不同的(你可以通过在一个翻译单元中定义一个'int * array [5];'然后尝试从另一个翻译单元使用'extern int * array [];'和b )'extern int **数组;' - 一个会工作)。 – 2013-05-02 11:40:59

1

按您的代码

int (*ptr)[] 

PTR是指向UNKNOWN size.So阵列至今编译器没有关于尺寸,其中想法ptr是指向的。当你试图创造一个增量时,编译器仍然不知道要增加多少。 一个指针增量将是sizeof(尖的元素)的一个增加。所以你得到错误“未指定的界限”。

现在为你剩下的两个问题,为了更好的理解,我允许我在一个问题中改写你的两个问题, “WHY(VOID *)IS BEHAVING LIKE(CHAR *)”??(hw was that :)?) 你的答案是

在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.

+0

这不是为什么编译器会像'char *'一样处理'void *'上的指针*算术*。在大多数系统中,int *和char *具有相同的表示和对齐要求,但对它们的算术表现不同。 'void *'上的算术是一个gcc特定的扩展;在标准C中,这是违反约束的。 – 2013-08-06 06:32:59

相关问题