在C中传递数组数组

tsv*_*der 0 c pointers

我需要一个带有2D数组并生成随机位的函数,因此结果是一个随机二进制字符串数组.

我有以下代码,

#define pop_size 50
#define chrom_length 50
main() {
    int population[pop_size][chrom_length];
    init_pop(&population);
}
int init_pop(int *population[][]) {
    for(i = 0; i < pop_size; i++) {
        for(j = 0; j < chrom_length; j++) {
            *population[i][j] = rand() % 2;
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在编译时,我收到以下错误消息:

数组类型具有不完整的元素类型

有什么建议?

Joh*_*ode 7

平常时间......

当数组表达式出现在大多数上下文中时,其类型将从"N元素数组T"隐式转换为"指向T",其值设置为指向数组的第一个元素.此规则的例外情况是,数组表达式是一个sizeof或一个运算&符的操作数,或者它是否是在声明中用作初始值设定项的字符串文字.

在代码的上下文中,这意味着什么?

表达式的类型population是" pop_size-element array chrome_lengthof int".按照上面的规则,在大多数情况下,表达式population将隐式转换为"指向chrome_length-element数组的指针"类型,或者int (*)[chrome_length].

&population但是,表达式的类型是"指向int的pop_size-element数组的chrome_length元素数组的指针",或者int (*)[pop_length][chrome_size],因为它population是一元运算&符的操作数.

请注意,这两个表达式具有相同的(数组的第一个元素的地址),但是不同的类型.

根据您编写的代码,您将函数称为

init_pop(&population);
Run Code Online (Sandbox Code Playgroud)

相应的函数定义应该是

int init_pop(int (*population)[pop_size][chrome_length]) // note that both dimensions
                                                         // must be specified
Run Code Online (Sandbox Code Playgroud)

你会访问每个元素

(*population)[i][j] = initial_value;
Run Code Online (Sandbox Code Playgroud)

注意,这意味着init_pop可以对付pop_sizeX chrome_length阵列; 你不能在不同大小的数组上使用它.

如果你将该功能称为

init_pop(population); // note no & operator
Run Code Online (Sandbox Code Playgroud)

然后必须有相应的函数定义

int init_pop(int (*population)[chrome_length]) // or population[][chrome_length],
                                               // which is equivalent
Run Code Online (Sandbox Code Playgroud)

你会访问每个元素

 population[i][j] = initial_value;
Run Code Online (Sandbox Code Playgroud)

请注意,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;
  ...
}
Run Code Online (Sandbox Code Playgroud)

现在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);
...
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,上述技巧仅适用于连续分配的 2D数组; 它不适用于动态分配的数组,其中主要维度和次要维度是分开分配的.

这是一个方便的表,假设定义int a[N][M]:

Expression     Type           Implicitly converted to
----------     ----           -----------------------
a              int [N][M]     int (*)[M]
a[i]           int [M]        int *
a[i][j]        int            
&a             int (*)[N][M]   


unw*_*ind 5

在将数组作为参数传递时,您需要告诉编译器除第一个之外的所有维度:

int init_pop(int population[][pop_size])
{ 
 ...
}
Run Code Online (Sandbox Code Playgroud)

是的,这意味着很难让它变得完全动态,并引入一个你必须重复自己的地方.

更新:我很困惑,并且要求倒置了.现在修复了.

  • 鉴于这是完全错误的事实,这个答案被3个赞成所接受,这有点可怕.您需要指定除*first*之外的所有尺寸. (5认同)