【问题标题】:Incrementing a 2D array in C在 C 中增加二维数组
【发布时间】:2021-10-01 20:24:46
【问题描述】:

我刚刚开始学习 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++;

【问题讨论】:

  • 将函数参数声明为数组时,编译器将其视为指针。所以参数声明int a[][3] 真的是int (*a)[3]。这就是为什么你可以增加它。当您在正确的数组上使用 ++ 时,这是不可能的,因为数组不能“递增”。

标签: arrays c multidimensional-array increment pre-increment


【解决方案1】:

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

不,你没有。至少在我知道的任何 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 个 ints 的数组的指针。因此,内部的++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()(没有持久存储)中的指针值,更不用说派生它的数组了。

当我在声明数组后尝试预递增数组时 main 函数我得到了以下错误。

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

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

【讨论】:

    【解决方案2】:

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

    ++a; //这是做什么的?

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

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

    它是一个指向一维数组的指针,它是二维数组的第一个元素,也就是数组的数组。增量发生后,它开始指向同一数组的 second 元素。如果您将 2D 数组视为矩阵,则它现在指向矩阵的第二行。这就是递增指针的作用。如果它之前指向数组的第 nth 个元素,那么它将指向之后的第 n+1th 元素(并且这个特定数组的元素是一维数组,也就是行)。

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

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

    没错,因为在main 中,a 是一个数组,而不是一个指针。你不能增加一个数组。

    【讨论】:

    • 感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    相关资源
    最近更新 更多