我很好奇我是否将 n>1 的 n 维数组作为函数的参数,是整个数组的内容被复制还是只是指向第一个元素的地址的指针。
假设函数签名是这样的:
int someFunction(int n, int arr[n][n]);
这是一个鲜为人知的 C99 扩展。数组仍然像往常一样通过引用传递,但编译器能够将其解释为类似于它处理可变长度数组的方式的数组。
当然,这不会给你边界检查。C没有那个。
在您的函数签名中,
int someFunction(int n, int arr[n][n]);
决赛n
并没有真正给你买任何东西,它只是被忽略了。不过int arr[n][]
是新的。这是C89所没有的。以前,唯一的选择是手动计算基指针的索引,arr[n*x+y]
.
在 Ansi-C (C89) 中,您必须将函数声明为,
int someFunction(int n, int arr[]);
这相当于
int someFunction(int n, int *arr);
并将两个维度计算为单个索引。
新的 C99 魔术,将原来的简化为:
int someFunction(int n, int *arr[n]);
我将这个过程更多地描述为数组采用,而不是通过。它只是减轻了最初决定将数组作为指针传递所带来的一些损失。
重要的是要了解后两个示例是某种内化的等价物。形象插图。在最后一个中,数组没有被转换为指针数组,而是删除了最低维度的边界。也许像这样更好地说明:
int someFunction(int n, int arr[n][]);
将数组复制为函数参数的唯一方法是将其包装在结构中。但是你不能有可变的尺寸。
struct arr {int n; int arr[n][n];}; //Nope, won't compile!
enum { n = 3 };
struct arr { int arr[n][n]; };
struct arr someFunction( struct arr ); //argument and return value are copied.
自 1989 年以来,这一直是合法的。
这是函数的非法签名,因为函数签名中的数组必须具有恒定的维度(最终维度除外)。
数组必须具有恒定大小作为函数参数的原因是因为它们实际上并没有在函数调用中被复制——只传递了一个指针。