是时候进行常规的演讲了...
当数组表达式出现在大多数上下文中时,它的类型会隐式地从“T 的 N 元素数组”转换为“指向 T 的指针”,并将其值设置为指向数组的第一个元素。此规则的例外情况是数组表达式是 sizeof 或一元 & 运算符的操作数,或者它是在声明中用作初始值设定项的字符串文字。
在您的代码上下文中,这一切意味着什么?
表达式population 的类型是“pop_size-element array of chrome_length-element arrays of int”。按照上面的规则,在大多数情况下,表达式population 将隐式转换为类型“指向chrome_length-int 元素数组的指针”或int (*)[chrome_length]。
然而,表达式&population 的类型是“指向pop_size-元素数组chrome_length-int 元素数组的指针”或int (*)[pop_length][chrome_size],因为population 是一元的操作数& 运营商。
请注意,这两个表达式具有相同的值(数组第一个元素的地址),但类型不同。
根据您编写的代码,您将函数调用为
init_pop(&population);
对应的函数定义应该是
int init_pop(int (*population)[pop_size][chrome_length]) // note that both dimensions
// must be specified
你可以访问每个元素
(*population)[i][j] = initial_value;
请注意,这意味着init_pop 只能处理pop_size x chrome_length 数组;你不能在不同大小的数组上使用它。
如果你调用函数为
init_pop(population); // note no & operator
那么对应的函数定义就必须是
int init_pop(int (*population)[chrome_length]) // or population[][chrome_length],
// which is equivalent
你可以访问每个元素
population[i][j] = initial_value;
请注意,在这种情况下,您不必显式取消引用 population。现在您可以处理具有不同种群大小的数组,但您仍然被固定的染色体长度所困扰。
第三种方法是将指向数组第一个元素的指针显式传递为指向 int 的简单指针,并将其视为一维数组,根据数组维度手动计算偏移量(作为单独的参数传递):
init_pop(&population[0][0], pop_size, chrome_length);
...
int init_pop(int *population, size_t pop_size, size_t chrome_length)
{
size_t i, j;
...
population[i*chrome_length+j] = initial_value;
...
}
现在 init_pop 可以用于不同大小的 int 二维数组:
int pop1[10][10];
int pop2[15][20];
int pop3[100][10];
...
init_pop(&pop1[0][0], 10, 10);
init_pop(&pop2[0][0], 15, 20);
init_pop(&pop3[0][0], 100, 10);
...
编辑:请注意,上述技巧仅适用于连续分配二维数组;它不适用于动态分配的数组,其中主要维度和次要维度是分开分配的。
这是一个方便的表格,假设定义为int a[N][M]:
表达式类型隐式转换为
---------- ---- ------------
一个 int [N][M] int (*)[M]
a[i] 整数 [M] 整数 *
a[i][j] 整数
&a 整数 (*)[N][M]