在 C 中定义类型时对指针语法感到困惑

confused about pointer syntax when defining type in C

在一些起始代码中我们有:

 /**
 * RGBTRIPLE
 *
 * This structure describes a color consisting of relative intensities of
 * red, green, and blue.   
 *
 * Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
 */
 typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

在我们的主程序中我们有:

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

我对 (*image) 感到困惑

如果我要定义一个指向 RGBTRIPLE 的指针,我想我会使用:

RGBTRIPLE *image[width] = ....

是否与以下内容相同:

RGBTRIPLE(*image)[width] = ....   ?

这些不一样。

RGBTRIPLE *image[width]

这表示一个大小为 width 的数组,其元素的类型为 RGBTRIPLE *,即它是一个指针数组。

RGBTRIPLE(*image)[width]

这是一个指向大小为 width 的数组的指针,其成员的类型为 RGBTRIPLE

两者都可用于实现二维数组,但方式不同。如果您使用前一个声明,则必须按如下方式分配额外维度:

int i;
for (i=0; i<width; i++) {
    image[i] = calloc(height, sizeof(RGBTRIPLE));
}
RGBTRIPLE *image[width]; 

是一个指向RGBTRIPLE的指针数组,这个数组将有width个元素。该数组中的每个指针都能够指向一个 RGBTRIPLE 对象,这使得当您每行有多个这样的对象时可以拥有一个二维数组。

分配比较混乱,因为您需要自己分配指针数组,然后分配每个指针指向的每一行,然后以相反的顺序释放内存。


RGBTRIPLE(*image)[width];

是指向RGBTRIPLE数组的指针,这个数组必须有width个元素,既然如此你可以用它来指向一个任意行数的二维数组只要它有 width 列数。

这是实现二维数组的更好方法,因为它有助于分配和释放。

它的工作原理是允许它通过递增指针以 width 字节大小的块移动指针,实际上它让您通过一次递增指针“跳转”到下一行。

例如width的6个和height的2个数组:

             +-----------+
image[0] ->  |0|1|2|3|4|5|
             +-----------+
             |5|4|3|2|1|0|
             +-----------+
                      
              
                      +-> image[0][4]
                      |
             +-----------+
             |0|1|2|3|4|5|
             +-----------+
image[1] ->  |5|4|3|2|1|0|
             +-----------+
                      |
                      +-> image[1][4]

表达式:

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

可能会更好,我会使用更安全的方法:

RGBTRIPLE(*image)[width] = calloc(height, sizeof *image);