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

Why don't I have to give the function the address of the array

本文关键字:数组 地址 函数 不必 为什么      更新时间:2023-10-16

嗨,我是C的新手,正在学习指针。我正在编写一个简单的递归函数来测试它,它使用参数int *aint size。在我的主要方法中,我预先使用&print_array发送数组的第一个字符的地址。

这似乎不起作用,我在编译时收到了一个"不兼容的指针类型"错误。我知道我可以删除&程序运行良好。我有个问题:

为什么我不能用&从main传入my_array的内存地址;?难道我不应该只给函数一个数组第一个元素的内存地址,它就可以处理剩下的吗?

谢谢,希望这个问题不要太无聊。

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

void print_array(int *a, int size){
    if (size>0){
            printf("%dn", 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 arrayn");
    for (i=0; i < 20; i++){
            printf("%dn", my_array[i]);
    }
    printf("The recursive method printn");
    print_array(&my_array, 20);
    return EXIT_SUCCESS;
}

是的,你可以给函数第一个元素的地址,让它处理剩下的。你可以这样做:

print_array(my_array, 20);

或:

print_array(&my_array[0], 20);

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

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

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

因此,只需切换到上面的一种形式(my_array&my_array[0])。更一般的一点是,要意识到,在大多数情况下,数组的名称计算为指向数组第一个元素的指针——值得注意的例外是,当您将数组的名称用作sizeof运算符的操作数或运算符的地址时(就像您在这里所做的那样)。在这两种情况下,数组的名称仍然指向整个数组,而不是指向第一个元素的指针。

函数需要一个指向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.cFAQ 第6节

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

6.3.2其他操作数

6.3.2.1值、数组和函数指示符

  1. 除非它是sizeof运算符、_Alignof运算符或一元&运算符,或是用于初始化数组的字符串文字,该表达式具有类型为"的类型"数组转换为类型为"pointer to type"的表达式,该表达式指向到数组对象的初始元素,并且不是左值。如果数组对象具有注册存储类,行为未定义