为什么我不必给函数提供数组的地址

时间:2015-02-21 02:37:06

标签: c++ c arrays pointers

您好我是C的新手并且学习指针。我正在编写一个简单的递归函数来测试参数int *aint size的位置。在我的main方法中,我事先使用print_array发送&我的数组的第一个字符的地址。

这似乎不起作用,我得到了一个"不兼容的指针类型"编译时出错。我明白我可以删除&并且程序运行正常。我有一个问题:

为什么我无法通过&amp ;?传递来自main的my_array的内存地址?难道我不能给函数提供数组第一个元素的内存地址,它可以处理剩下的吗?

谢谢,希望这个问题不是太棒了。

 #include <stdio.h>
 #include <stdlib.h>


void print_array(int *a, int size){
    if (size>0){
            printf("%d\n", a[0]);
            print_array(a+1, size-1);
    }
}

int main(void){
    int my_array[20];
    int i;

    for (i=0; i < 20; i++){
            my_array[i] = rand() % 20;
    }

    /*the contents of the array*/
    printf("The contents of the array\n");
    for (i=0; i < 20; i++){
            printf("%d\n", my_array[i]);
    }

    printf("The recursive method print\n");

    print_array(&my_array, 20);

    return EXIT_SUCCESS;

}

3 个答案:

答案 0 :(得分:6)

是的,您可以为函数提供第一个元素的地址,并让它处理其余元素。您可以这样做:

print_array(my_array, 20);

...或:

print_array(&my_array[0], 20);

不幸的是,虽然&my_array是合法代码,但它会生成指向整个数组的指针,而不是指向数组第一个元素的指针。那些具有相同的地址,但是不同的类型,这是造成错误的原因。

指针的类型决定(除此之外)该指针的算术运算方式。在您的情况下,print_array打印数组中的第一个int,然后将一个添加到指针。由于它是指向int的指针,因此该添加实际上将int的大小添加到指针中的地址。

如果您使用指向整个数组的指针,那么添加一个指针会将整个数组的大小添加到地址中。例如,假设4字节的整数和my_array的基地址为1000.在这种情况下,my_array+1将产生1004,因此它保存数组中第二个int的地址(正如您无疑想要的那样) )。相比之下,&my_array将获取整个数组的地址,类型为“指向20个整数的数组的指针”。当你向它添加一个时,它会将指向类型的大小加1到地址,因此你将获得1080(即整个数组是20 * 4 = 80字节)。这显然是你想要的 - 而不是x+1指向数组中的第二项,它现在指向数组的末尾,并且试图取消引用指针将给出未定义的行为。

因此,只需切换到上面的表单之一(my_array&my_array[0])即可。更一般的说法是,在大多数情况下,要意识到数组的名称作为指向数组第一个元素的指针来计算 - 值得注意的例外是当您使用数组的名称作为{{的操作数时1}}运算符或运算符地址(如此处所示)。在这两种情况下,数组的名称仍然引用整个数组,而不是指向第一个元素的指针。

答案 1 :(得分:2)

你的函数需要一个指向int的指针,特别是数组的第一个(第0个)元素的地址。

通过调用print_array(&my_array, 20);,您尝试传递整个数组的地址,类型int(*)[20]的值与int*不同。它指向相同的内存位置,但它的类型不同。

要传递第一个元素的地址,您可以写:

print_array(&my_array[0], 20);

或等同于:

print_array(my_array, 20);

后者的工作原理是,在大多数但不是所有的上下文中,数组的名称被隐式转换为指向其第一个元素的指针。

C和C ++中数组和指针之间的关系可能令人困惑。推荐阅读:comp.lang.c FAQ

的第6部分

答案 2 :(得分:0)

因为数组会自动衰减为指针,所以从n1570草案中提取以下内容

  

6.3.2其他操作数

     

6.3.2.1左值,数组和函数指示符

     
      
  1. 除非是sizeof运算符,_Alignof运算符或者&运算符的操作数。   一元{{1}}运算符,或者是用于初始化数组的字符串文字,一个包含的表达式   类型''数组''转换为类型为''指向类型'指针的表达式   到数组对象的初始元素,而不是左值。如果数组对象有   注册存储类,行为未定义。
  2.