【发布时间】:2019-06-20 04:12:43
【问题描述】:
这个问题源于 Eric Postpischil in another thread. 的评论
我很难理解使用可变长度数组 (VLA) 作为函数参数:
- 未检查数组大小。
- 数组大小无法从数组中恢复,因为标准类型调整数组 -> 指针也适用于 VLA,如下面的
sizeof()调用所示;即使完全有可能将整个数组传递到堆栈上,就像 VLA 在定义时在堆栈上创建一样。 - 大小必须作为附加参数传递,与指针一样。
那么为什么语言允许使用 VLA 参数声明函数,如果它们没有提供任何优势并且像指针的任何其他数组参数一样被调整?如果语言不使用大小表达式(例如检查实际参数的大小)并且在函数内部无法获得(仍然必须为此传递显式变量),为什么要评估大小表达式??
为了更清楚我的困惑,请考虑以下程序(现场示例here)。所有函数声明显然是等价的。但正如 Eric 在另一个线程中指出的那样,函数声明中的参数大小表达式在运行时评估。大小表达式不会被忽略。
我不清楚这会有什么好处,因为大小及其评估没有任何影响(除了可能的副作用)。特别是,重复我自己,该信息不能被函数内部的代码使用。最明显的变化是在堆栈上传递 VLA,就像结构一样。毕竟,它们通常也在调用方的堆栈上。但是就像固定长度的数组一样,类型在声明时就已经调整为一个指针——下面的所有声明都是等价的。尽管如此,还是会评估无用和丢弃的数组大小表达式。
#include <stdio.h>
// Nothing to see here.
extern void ptr(int *arr);
// Identical to the above.
extern void ptr(int arr[]);
// Still identical. Is 1 evaluated? Who knows ;-).
extern void ptr(int arr[1]);
// Is printf evaluated when called? Yes.
// But the array is still adjusted to a pointer.
void ptr(int arr[printf("Call-time evaluation of size parameter\n")]){}
// This would not compile, so the declarations above must be equivalent.
// extern void ptr(int **p);
int main()
{
ptr(0);
ptr(0);
return 0;
}
【问题讨论】:
-
@ChronoKitsune:这个问题主要不是关于阵列衰减。实际上,它根本不涉及数组衰减;涉及的具体问题是另一方面,参数类型调整。但这不是主要问题。
-
@ChronoKitsune 问题涉及数组衰减(或者更确切地说,参数类型调整),但这不是问题的主要焦点。该问题询问评估大小参数的时间。如果将 VLA 视为普通数组,我还想知道允许 VLA 作为函数参数的基本原理。你知道,它们可以像结构一样按值传递;如a Q&A I posted a while ago. 中所述,使用固定大小的数组仅具有有限的意义。
-
@ChronoKitsune 那么为什么根本不使用 VLA 参数的大小,甚至不是实际参数的大小??
-
@JeanFrancois 这不是您链接的众所周知的问题的重复。
-
@JeanFrancois:这个问题不是关于何时或为何将数组转换为指针或何时将数组参数类型调整为指针类型。这个问题是关于数组参数中大小表达式的评估。请不要不恰当地将问题标记为重复。
标签: c parameter-passing language-lawyer variable-length-array