传递 &arr(整个块的地址)或仅传递数组名称(第一个元素的地址)有什么区别吗?

Is there any difference in passing &arr(address of entire block) or just passing name of array (address of first element)?

void func1(int* ptr)
{
    printf("func1 :%d\n",++ptr);
}

int main()
{
    int arr[4] = {0,1,2,3};
    printf("Addr enter code here`f arr: %d\n",arr);
    func1(arr);  // first way:
    func1(&arr); // second way: How this will be different from func1(arr). 
}

数组衰减为指针。这些指针中的任何一个都引用内存中的相同地址。区别在于这个指针的类型。

int arr[5];
  1. arr&arr[0] 的类型为 指向 int 的指针 (int *)
  2. &arr 的类型为 指向五个元素整数数组的指针 ( int (*)[5])

我们有一个名为 func1 的函数,它接受一个 指向 int 的指针,也就是说,它的参数是 int*。现在让我们看看每种情况下发生了什么。

案例一

在这种情况下我们有 func1(arr);

这里的变量 arr 是一个 数组,大小为 4,元素类型为 int(即 int [4]),但它 [由于类型衰减,=61=]衰减到第一个元素(即int*)的指针.

所以当你写的时候,

func1(arr);

本质上,您将 int* 作为 参数 传递, 匹配 与函数类型 参数.

案例二

在这种情况下我们有 func1(&arr);

此处&arr表示指向大小为4且元素类型为int的数组的指针。(即int (*)[4])。

现在当你写的时候,

func1(&arr);

本质上,您将 int (*)[4] 作为 参数 传递给函数 func1。但是注意func1参数int*类型的。所以在参数类型和参数中存在不匹配

现在在您发布的屏幕截图中,程序似乎正在编译和执行成功。但请注意,由于在第二种情况下,参数和参数类型中存在 不匹配,您将得到 未定义的行为

Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely on the output of a program that has undefined behavior.


1有关未定义行为的更准确的技术定义,请参阅 this 其中提到:没有对程序行为的限制.

&arrarr的区别在于前者的类型是指向数组的指针int (*)[4],后者的类型是数组int[4]它可以衰减到指向第一个元素 int* 的指针。指向数组的指针和指向第一个元素的衰减指针都指向同一个地址,因为数组的第一个字节也是数组第一个元素的第一个字节。

func1(&arr)func1(arr) 的区别在于前者格式错误,因为 int (*)[4] 不会隐式转换为 int*。为了能够调用 func1(&arr),您必须接受正确类型的指针:

void func1(int (*ptr)[4])

printf("func1 :%d\n",++ptr);
printf("Addr enter code here`f arr: %d\n",arr);

这两个调用都会导致未定义的行为。可变参数的类型必须与格式说明符所需的类型相匹配。您使用了格式说明符 %d,它要求参数的类型为 int(或类似)。这里的(衰减的)参数的类型是 int* 而不是 int.