C中可变大小的二维数组

Jam*_*mes 2 c arrays pointers

所以我一直在尝试将 PPM 文件存储在要操作的程序中,我成功地存储了直到颜色的所有内容,我在颜色方面取得了进展。

在询问有关堆栈溢出( For 循环无缘无故停止)的问题时,我确信我的方法有点粗制滥造,但是我不明白使用以下内容的原因:

COLOR (*colors)[width] = malloc( sizeof(COLOR[height][width]) );
Run Code Online (Sandbox Code Playgroud)

有人可以准确地分解这行代码在做什么并解释它是什么类型吗?所以我可以将它存储在一个结构中并成功返回它。

示例:以前我使用指针到指针,我分配了一个高度,并为每个指针分配了一个宽度。这意味着我可以为每个指针创建一个颜色,沿着宽度递增它直到最后,然后重置指针并递增高度和循环。获得完整图像后,我将其返回以将其存储在以下位置:

typedef struct {
    char code[CODE_LENGTH];
    COMMENT *commentPPM;
    int width, height, max;
    COLOR **colorValues;
} PPM;
Run Code Online (Sandbox Code Playgroud)

使用:

ppmFile->colorValues = getColors(fd, ppmFile->width, ppmFile->height);
Run Code Online (Sandbox Code Playgroud)

typedef struct{
    int red, green, blue;
} COLOR;

COLOR * getNextColor(FILE *fd);

COLOR **getColors(FILE *fd, int width, int height){
    printf("\nentered get colors");
    COLOR **colors = malloc(sizeof(COLOR*)*height);
    printf("\nallocated %d space height",height);

    int i,j;
    for(i = 0; i < height; i++, colors++){
        *colors = malloc(sizeof(COLOR)*width);
        printf("\nallocated %d space width",width);
        for(j = 0; j < width; j++, *(colors++)){
            printf("\nlooping through to get the colors for point (%d,%d)", j,i); 
            //*colors = getNextColor(fd);
        }
        *colors -= width;
        printf("\nmoved the pointer for *colors back %d spaces",width);
    }

    colors -= height;
    printf("\nmoved the pointer for colors back %d spaces",height);

    return colors;
}
Run Code Online (Sandbox Code Playgroud)

Lun*_*din 5

为了理解这一点,您需要首先理解以下概念:

  • 数组指针(不要与指向第一个元素的指针混淆)
  • 变长数组,也称为 VLA。

鉴于您已经知道上面是什么,那么最正式的正确方法是声明一个指向 2D VLA 的数组指针:

COLOR (*colors)[height][width];
Run Code Online (Sandbox Code Playgroud)

当你调用 malloc 时,你告诉它为这样的数组分配足够的空间:

malloc( sizeof(COLOR[height][width]) )
Run Code Online (Sandbox Code Playgroud)

那么你最终会得到

colors = malloc( sizeof(COLOR[height][width]) );
Run Code Online (Sandbox Code Playgroud)

但是,由于colors在此示例中是一个数组指针,因此每次您希望访问该数组时都必须取消引用它:

(*colors)[i][j] = something;
Run Code Online (Sandbox Code Playgroud)

这种语法不实用而且难以阅读。

因此,您可以使用另一个技巧,在声明数组指针时跳过最内层的维度。您可以跳过最内层维度并仅声明指向一维数组的数组指针,而不是指向二维数组的指针:

COLOR (*colors)[width]
Run Code Online (Sandbox Code Playgroud)

但使用与以前相同的 malloc 调用。因为现在您可以利用数组指针算术:

colors[i][j] = something;
Run Code Online (Sandbox Code Playgroud)

这本质上意味着“在我的数组数组中,给我数组编号i,项目编号j”。

它的工作原理与工作原理相同int* x = malloc(sizeof(int[n])); ... x[i] = something;,当然,工作原理会给你int数字i