在 C 中递增二维数组

Incrementing a 2D array in C

我刚开始学习 C 中的二维数组,我遇到了这段代码,其中二维数组像这样直接预递增 ++array

我尝试在 3 个不同的地方打印矩阵(初始化后,增量后的函数中,函数调用后的主函数中),但我不明白预增量是如何工作的。

我也注意到 a[1][1]++ 反映在原始矩阵中(8 递增到 9),但没有别的。

#include <stdio.h>
void printmatrix(int[3][3]);
int function(int a[][3])
{
    int i,j;
    ++a; //what does this do?
    printf("In function...\n");
    printmatrix(a);
    a[1][1]++;
}
void printmatrix(int a[3][3])
{
    int i,j;
    for(i=0;i<3;i++)
    {
        for(j=0;j<3;j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
printf("Initially...\n");
printmatrix(a);
function(a);
printf("In main...\n");
printmatrix(a);
printf("a[2][1]-a[1][2]=%d",a[2][1]-a[1][2]);
return 0;
}

我得到的输出是,

Initially...
1 2 3 
4 5 6 
7 8 9 

In function...
4 5 6 
7 8 9 
32765 0 0 

In main...
1 2 3 
4 5 6 
7 9 9 

a[2][1]-a[1][2]=3

此外,当我在主函数中声明数组后尝试预递增数组时,出现以下错误。

int a[3][3]={1,2,3,4,5,6,7,8,9};
a++;
main.c: In function ‘main’:
main.c:28:2: error: lvalue required as increment operand
 a++;

你不能增加一个数组,那是没有意义的。您可以增加一个指针。指针和数组是两个不同的东西。

++a; //what does this do?

这增加了一个指针,因为a是一个指针。虽然它被声明为int a[][3],但它不是一个二维数组。

为什么是指针而不是数组?因为它是一个函数参数。函数参数不能是数组。您可以用方括号声明它,但它仍然不是数组。它与 int (*a)[3] 的含义完全相同——仅当它是一个函数参数时。在 printmatrix 也是。这很重要.

它是一个指向一维数组的指针,它是二维数组的第一个元素a.k.a。数组的数组。增量发生后,它开始指向同一数组的 second 元素。如果您将二维数组视为矩阵,它现在指向矩阵的第二行。这就是递增指针的作用。如果它之前指向数组的第 n 个元素,它将指向之后的第 n+1 个元素(这个特定数组的元素是一维数组,a.k.a. 行)。

这使得打印发生在 printmatrix(a); 未定义行为 中。 a 现在指向二维数组的 second 元素,但 printmatrix 不知道它,打印时好像它前面还有 3 行.

Also when I tried to pre-increment the array after declaring it in the main function I got the following error.

没错,因为在main中,a是数组,不是指针。您不能递增数组。

I have just started learning 2D arrays in C and I came across this code where a 2D array is directly pre-incremented like this ++array.

不,你没有。至少在我知道的任何 C 编译器都会接受的程序中不会。数组通常包含可修改的元素,但整个数组不是可修改的单元。

在这个函数中...

int function(int a[][3])
{
    int i,j;
    ++a; //what does this do?
    printf("In function...\n");
    printmatrix(a);
    a[1][1]++;
}

...虽然参数a是用数组的语法表达的,但实际上是指针,不是数组。这是 C 的一个怪癖,尽管它与数组周围的其他 C 语义非常一致。函数签名等同于 ...

int function(int (*a)[3])

...,它将 a 声明为指向 3 int 数组的指针。因此,其中的 ++a 具有其正常效果:它计算指向 *a 之后的下一个 int[3] 的指针,并更新 a 以指向它。

现在考虑 main():

int main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
printf("Initially...\n");
printmatrix(a);
function(a);
// [...]

main() 中,标识符 a 指定一个二维数组,但有几个值得注意的例外,无论它出现在表达式中的什么地方,它都会被转换为指向其第一个元素的指针。这样的指针具有 function() 期望其参数的类型,因此函数调用很好。

请注意,C 函数调用具有严格的按值传递语义。该函数接收它自己的该指针副本,因此它所做的更改不会影响 main()(没有持久存储)中的指针值,更不用说它派生的数组了。

Also when I tried to pre-increment the array after declaring it in the main function I got the following error.

int a[3][3]={1,2,3,4,5,6,7,8,9};
a++;

正如我已经写过的,整个数组是不可修改的。但是,您的编译器生成的诊断消息有点偏离。该片段中的 a 是一个左值。但它不是 可修改的 左值,这是预增量和 post 增量运算符对操作数的要求。