C++ 为什么不';我必须给函数一个数组的地址

C++ 为什么不';我必须给函数一个数组的地址,c++,c,arrays,pointers,C++,C,Arrays,Pointers,嗨,我是C新手,正在学习指针。我正在编写一个简单的递归函数来测试它,其中包含参数int*a和int size。在我的main方法中,我预先使用和发送打印数组数组第一个字符的地址 这似乎不起作用,我在编译时遇到了一个“不兼容的指针类型”错误。我知道我可以删除&并且程序运行良好。我有一个问题: 为什么我不能用&?从main传入我的_数组的内存地址?我不应该只给函数数组第一个元素的内存地址,它就可以处理其余的吗 谢谢,希望这个问题不是太难回答 #include <stdio.h> #i

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

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

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

谢谢,希望这个问题不是太难回答

 #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;

}
#包括
#包括
无效打印_数组(整数*a,整数大小){
如果(大小>0){
printf(“%d\n”,a[0]);
打印_数组(a+1,大小-1);
}
}
内部主(空){
int my_数组[20];
int i;
对于(i=0;i<20;i++){
my_数组[i]=rand()%20;
}
/*数组的内容*/
printf(“数组的内容”);
对于(i=0;i<20;i++){
printf(“%d\n”,我的数组[i]);
}
printf(“递归方法print\n”);
打印数组(&我的数组,20);
返回退出成功;
}

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

print_array(my_array, 20);
…或:

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

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

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


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

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

6.3.2其他操作数

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

  • 除非它是
    sizeof
    运算符、
    \u Alignof
    运算符或 一元
    &
    运算符,或是用于初始化数组的字符串文字,一个具有 类型“”的数组“”已转换为类型为“”指向类型“”的指针的表达式 指向数组对象的初始元素,并且不是左值。如果数组对象具有 注册存储类,行为未定义

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

    通过调用
    print_数组(&my_数组,20)
    ,您试图传递整个数组的地址,类型为
    int(*)[20]
    ,与
    int*
    不同。它指向相同的内存位置,但属于不同的类型

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

    print_array(&my_array[0], 20);
    
    或者,相当于:

    print_array(my_array, 20);
    
    后者之所以有效,是因为在大多数(并非所有)上下文中,数组的名称隐式转换为指向其第一个元素的指针


    < > C和C++中数组和指针之间的关系可能会混淆。建议阅读:

    第6节注意,关于
    \u Alignof
    运算符的措辞不正确,已从最终C11标准中删除。与
    sizeof
    不同,
    \u Alignof
    只能应用于类型,而不能应用于表达式。(原因尚不清楚。)@KeithThompson谢谢你的评论,我没有
    C11
    标准。只有草稿。如果
    print\u array
    的第一个参数声明为
    int(*a)[20]
    ,那么您可以将
    &my\u array
    传递给它。但是
    int*a
    是指向整数的指针,而不是指向20个整数数组的指针。这就是为什么必须传递数组第一个元素的地址,而不是数组本身的地址(即使它们具有相同的数值)。@Wyzard:是的,如果参数声明为
    int(*a)[20]
    ,则可以传递
    &my_数组
    ,但是
    print\u数组
    内部的
    a+1
    将产生未定义的行为。“不幸的是,虽然&my\u数组是合法代码,但它会产生一个指向整个数组的指针,即ra