在 C/C++ 中将数组作为形式参数传递为 int arr[] 和 int arr[N] 之间的区别
Posted
技术标签:
【中文标题】在 C/C++ 中将数组作为形式参数传递为 int arr[] 和 int arr[N] 之间的区别【英文标题】:Difference between passing an array as formal parameter as int arr[] and int arr[N] in C/C++ 【发布时间】:2019-12-26 17:41:04 【问题描述】:我被接受的答案和下面的 cmets 弄糊涂了,他们说的是相反的事情 在Passing Arrays to Function in C++。
作为函数的形式参数将数组作为int arr[]
或int arr[N]
传递有什么区别?也就是说void foo(int arr[])
和void foo(int arr[N])
有区别吗?
【问题讨论】:
最佳答案说它们彼此等价并且与int *
等价。这是正确的答案。
您可以通过获取问题中的函数声明并让编译器尝试区分两者来自己获得答案。 const int N = 10; void foo(int arr[]); void foo(int arr[N]);
你会看到它can't be done
评论员没有仔细阅读答案。答案涵盖了所有的基础,而 cmets 是无关紧要的。
如果您只想区分不同的参数,则必须使用引用:void f(int (&a)[4])
和 void f(int (&a)[8])
是不同的函数,必须使用指定大小的数组调用。
已经使用std::array
或std::vector
。忘记存在 C 风格的数组吧。
【参考方案1】:
void foo(int arr[])
和 void foo(int arr[N])
完全相同。这是因为作为函数参数的数组被调整为指针。所以以上两个都转化为:
void foo(int *arr)
这在C standard 的第 6.7.6.3p7 节中关于“函数声明符”进行了指定:
将参数声明为“类型数组”应调整为 ''qualified pointer to type'', 类型限定符(如果 any) 是在数组类型的
[
和]
中指定的那些 推导。如果关键字static
也出现在[
和数组类型推导的]
,然后对于每次调用 函数,对应实参的值 应提供对数组第一个元素的访问,至少为 由大小表达式指定的许多元素。
类似的语言存在于第 11.3.5p5 节 C++ standard:
一个名称可以在一个单一名称中用于多个不同的功能 范围;这是函数重载(第 16 条)。的所有声明 函数应在返回类型和返回值上完全一致 参数类型列表。函数的类型由使用 遵循规则。每个参数的类型(包括函数 参数包)由它自己的 decl-specifier-seq 和 声明者。 确定每个参数的类型后,任意 类型为“T 数组”或函数类型 T 的参数被调整为 “指向 T 的指针”。 在生成参数类型列表后,任何 修改参数类型的*** lcv 限定符在以下情况下被删除 形成函数类型。转换参数的结果列表 类型以及省略号或函数的存在与否 参数包是函数的参数类型列表。[注意:这个 转换不影响参数的类型。
【讨论】:
如果N
是一个表达式,而不仅仅是一个简单的常量,那么参数声明int arr[]
和int arr[N]
在C 中是不等价的。在后者中,N
被评估,即使参数类型调整为int *arr
。 (我不肯定 C 标准要求这样做,但它至少允许这样做,Clang 和 GCC 都这样做。)例如,#include <stdio.h>
/ static void foo(int a[printf("Hello\n")]) int main(void) foo(0);
,打印“Hello”。
@EricPostpischil 我永远不会猜到。我想知道为什么语法允许它?
这可能比更改它更麻烦,因为您必须允许不在最外层的数组中使用大小表达式,如int a[][x]
,并且必须对这些表达式求值,以便调用函数知道大小。在语法中处理最外层维度可能是一个麻烦。虽然已经有一些变化; int a[static 4]
在参数中表示 a
指向一个至少有 4 个元素的地方(因此 a
不能是空指针)。以上是关于在 C/C++ 中将数组作为形式参数传递为 int arr[] 和 int arr[N] 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章