我正在尝试编写一个函数来交换2D数组中的2个元素:
void swap(int surface[][], int x1, int y1, int x2, int y2) {
int temp = surface[x1][y1];
surface[x1][y1] = surface[x2][y2];
surface[x2][y2] = temp;
}
然而,当我尝试编译它(gcc)时,我收到此错误消息:
Sim_Annealing.c: In function `swap':
Sim_Annealing.c:7: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:9: error: invalid use of array with unspecified bounds
为了将2D数组作为函数参数,我是否需要做一些特殊的魔术?
感谢您的帮助。如果你知道数组的任何好的引用作为函数参数发送它们的方式:)
答案 0 :(得分:6)
只需声明数组参数即可。更好的是,对初始声明和函数的形式参数使用typedef。
问题在于,在不知道行大小(即列数)的情况下,它无法计算指针调整以获得后续行。有趣的是,它不需要知道你有多少行。
例如,这有效:
void swap(int surface[][20], int x1, int y1, int x2, int y2) {
int temp = surface[x1][y1];
surface[x1][y1] = surface[x2][y2];
surface[x2][y2] = temp;
}
但最好将调用者的类型和函数的类型绑定在一起。
每个下标访问都需要乘法,但这是有效的(只符合C99的编译器)......
int f(int, int, int a[*][*]);
int f(int r, int c, int a[r][c])
{
return a[99][100];
}
另一个例子,即使在C89之前的环境中也可以使用:
typedef int surface_t[][20];
surface_t therealthing = {
{ 1, 2, 3},
{ 4, 5, 6}
};
void swap(surface_t x) {
x[0][2] = 'q';
}
void f1(void) {
swap(therealthing);
}
最后,因为变长数组是最新的,传统且仍然最快的技术是通过int *a[]
。这不需要任何行或列长度的知识,但您需要构造指针向量。
答案 1 :(得分:1)
如果数组是“真正的”2D数组,则需要指定除第一维之外的所有数组的大小:
void swap(int surface[][NUMBER_OF_COLUMNS], int x1, int y1, int x2, int y2) {
...
}
这有一些潜在的问题。如果您的2D数组实际上是指针数组(int *surface[]
),那将无效,您需要将surface
参数更改为指向指针的指针:
void swap(int **surface, int x1, int y1, int x2, int y2) {
...
}
或者,为了使函数更通用,您可以将其更改为接受两个int指针(可以指向任何位置)并交换它们:
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
你可以这样称呼它:
swap(&surface[x1][y1], &surface[x2][y2]);
答案 2 :(得分:1)
在C中,只允许未指定数组的第一个维度,因为它需要知道如何计算偏移量。如果你需要在我们的数组中使用可变大小的2D数组传递作为int *,请传递第二个维度的大小并自己传递指针数学:
void swap(int *surface, int ySize, int x1, int y1, int x2, int y2) {
int temp = *(surface + ySize * x1 + y1) ;
*(surface + ySize * x1 + y1) = *(surface + ySize * x2 + y2);
*(surface + ySize * x2 + y2) = temp;
}
这与[] []语法的作用相同,因为C中的数组实际上只是指针。
答案 3 :(得分:1)
GCC允许可变长度数组作为函数的参数:
#include <stdio.h>
void swap(int size; int surface[][size], int size, int x1, int y1, int x2, int y2) {
int temp = surface[x1][y1];
surface[x1][y1] = surface[x2][y2];
surface[x2][y2] = temp;
}
int s[10][10];
int main(){
s[1][1] = 11;
s[2][2] = 22;
printf("s[1][1]: %i s[2][2]: %i\n", s[1][1], s[2][2] );
swap( s, 10, 1, 1, 2, 2 );
printf("s[1][1]: %i s[2][2]: %i\n", s[1][1], s[2][2] );
return 0;
}
答案 4 :(得分:1)
将多维数组作为函数参数传递会引起一些令人头疼的问题。请记住,在大多数上下文中,数组类型的表达式将隐式转换为指针类型,其值将是数组的第一个元素的地址。因此,例如,一个10x20的int数组将转换为指向一个20元素的int数组的指针:
void swap(int (*surface)[20], size_t rows, size_t x1, size_t x2,
size_t y1, size_t y2)
{
int temp;
assert(x1 < rows && x2 < rows);
temp = surface[x1][y1];
surface[x1][y1] = surface[x2][y2];
surface[x2][y2] = temp;
}
int main(void)
{
int surface[10][20];
...
swap(surface, 10, 1, 1, 2, 2);
...
}
这是一个大问题出现的地方。基于其原型,swap()只能处理Nx20的int数组;行数可以变化,但列数不能,因为T (*)[N]
是与T (*)[M]
不同的类型,其中N!= M.理想情况下,你想要一个可以处理任意数字的函数行和列。实现此目的的一种方法是将数组视为T的一维数组,并手动计算行和列偏移:
void swap(int *surface, size_t rows, size_t cols, size_t x1,
size_t x2, size_t y1, size_t y2)
{
int temp;
assert(x1 < rows && x2 < rows && y1 < cols && y2 < cols);
temp = surface[x1*cols+y1];
surface[x1*cols+y1] = surface[x2*cols+y2];
surface[x2*cols+y2] = temp;
}
int main(void)
{
int surface[10][20];
...
swap(&surface[0][0], 10, 20, 1, 1, 2, 2);
}
这里我们传递第一个元素的地址(&amp; surface [0] [0])并将其视为指向int的简单指针。这样我们就可以处理任意数量的行和列。请注意,这仅适用于实际的2D数组(不是指针数组),因为swap假定数组元素是连续布局的。