数组类型 - 分配/用作函数参数的规则 [英] Array Type - Rules for assignment/use as function parameter

查看:26
本文介绍了数组类型 - 分配/用作函数参数的规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我需要将数组传递给函数时,该函数的以下所有声明似乎都可以使用

when I need to pass an array to a function, it seems all the following declarations of the function will work

void f(int arr[])  
void f(int arr[4]) // is this one correct?

为此:

int a[]={1,2,3,4};
f(a);

但是当我将一个数组分配给另一个数组时,它失败了

But when I assign an array to another array, it fails

int a[]={1,2,3,4};
int b[4] = a; // error: array must be initialized with a brace-enclosed initializer

那么为什么一个数组作为函数的参数传递是可以的,但是用在简单赋值的rhs上却是错误的?

So why an array passed as an argument of a function is okay, but used on the rhs of simple assignment is wrong?

推荐答案

为了理解差异,我们需要理解两个不同的上下文.

For understanding the difference, we need to understand two different contexts.

  • value 上下文中,T 类型的数组的名称相当于一个指向 T 类型的指针,并且等于一个指向数组第一个元素的指针.
  • object 上下文中,T 类型的数组的名称不会简化为指针.
  • In value contexts, the name of an array of type T is equivalent to a pointer to type T, and is equal to a pointer to the array's first element.
  • In object contexts, the name of an array of type T does not reduce to a pointer.

什么是对象上下文?

a = b; 中,a 在对象上下文中.当您获取变量的地址时,它会在对象上下文中使用.最后,当您在变量上使用 sizeof 运算符时,它是在对象上下文中使用的.在所有其他情况下,变量用于值上下文.

In a = b;, a is in object context. When you taken the address of a variable, it's used in object context. Finally, when you use sizeof operator on a variable, it's used in object context. In all other cases, a variable is used in value context.

既然我们有了这些知识,当我们这样做时:

Now that we have this knowledge, when we do:

void f(int arr[4]);

完全等价于

void f(int *arr);

如您所见,我们可以从函数声明中省略大小(上面的 4).这意味着您无法知道传递给 f() 的数组"的大小.稍后,当您这样做时:

As you found out, we can omit the size (4 above) from the function declaration. This means that you can't know the size of the "array" passed to f(). Later, when you do:

int a[]={1,2,3,4};
f(a);

在函数调用中,名称a 位于值上下文中,因此它简化为指向int 的指针.这很好,因为 f 需要一个指向 int 的指针,所以函数定义和使用匹配.传递给 f() 的是指向 a (&a[0]) 第一个元素的指针.

In the function call, the name a is in value context, so it reduces to a pointer to int. This is good, because f expects a pointer to an int, so the function definition and use match. What is passed to f() is the pointer to the first element of a (&a[0]).

int a[]={1,2,3,4};
int b[4] = a;

名称 b 用于对象上下文中,不会简化为指针.(顺便说一句,这里的a在一个值上下文中,并简化为一个指针.)

The name b is used in a object context, and does not reduce to a pointer. (Incidentally, a here is in a value context, and reduces to a pointer.)

现在,int b[4]; 分配 4 个 int 的存储价值,并为其命名 b.a 也被分配了类似的存储空间.因此,实际上,上述分配的意思是我想让存储位置与之前的位置相同".这没有意义.

Now, int b[4]; assigns storage worth of 4 ints and gives the name b to it. a was also assigned similar storage. So, in effect, the above assignment means, "I want to make the storage location the same as the previous location". This doesn't make sense.

如果你想将a的内容copyb中,那么你可以这样做:

If you want to copy the contents of a into b, then you could do:

#include <string.h>
int b[4];
memcpy(b, a, sizeof b);

或者,如果你想要一个指向 a 的指针 b:

Or, if you wanted a pointer b that pointed to a:

int *b = a;

这里,a 在值上下文中,并简化为指向 int 的指针,因此我们可以将 a 分配给 int *.

Here, a is in value context, and reduces to a pointer to int, so we can assign a to an int *.

最后,在初始化数组时,您可以为其分配显式值:

Finally, when initializing an array, you can assign to it explicit values:

int a[] = {1, 2, 3, 4};

这里,a 有 4 个元素,初始化为 1、2、3 和 4.你也可以这样做:

Here, a has 4 elements, initialized to 1, 2, 3, and 4. You could also do:

int a[4] = {1, 2, 3, 4};

如果列表中的元素少于数组中的元素数,那么其余的值都被认为是0:

If there are fewer elements in the list than the number of elements in the array, then the rest of the values are taken to be 0:

int a[4] = {1, 2};

设置 a[2]a[3] 为 0.

sets a[2] and a[3] to 0.

这篇关于数组类型 - 分配/用作函数参数的规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆