**如何在二维数组中工作?

时间:2017-10-07 10:43:24

标签: c pointers multidimensional-array

int main(void) {
    unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)};
    printf("%d, %u, %u, %u \n",**x, **(x+1), **(x+2), **(x+3));
    return 0;
}

上述代码的输出为3,12,0,0。 不应该是1,4,7,17​​,因为x存储了数组第一个元素的地址吗?

当我试图打印时

printf("%u, %u \n", x, &x[0][0] );

它显示相同的地址2108666688,2108666688

但是当我尝试使用

打印数组时
for(int i = 0; i<4; ++i)
{
    for(int j = 0; j<3 ; ++j)
    {
        printf("%d ",x[i][j]);
    }
    printf("\n");
}

我看到输出为

3 6 9 
12 0 0 
0 0 0 
0 0 0 

那么,到底发生了什么?为什么没有将数字正确分配给数组?

3 个答案:

答案 0 :(得分:6)

unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)};

在功能上等同于:

unsigned int x[4][3] = {3, 6, 9, 12};

因为comma operator在这里工作!逗号运算符计算其所有操作数并生成其最后一个操作数的结果。

所以你看到的输出是预期的。你可能意味着:

unsigned int x[4][3] = {{1,2,3},{4,5,6},{7,8,9},{17,11,12}};

答案 1 :(得分:1)

请记住,数组会自然地衰减到指向第一个元素的指针。这意味着,在您的情况下,x本身与&x[0]相同。

因为x是数组数组,&x[0]的类型是指向数组的指针,在本例中为unsigned int (*)[3]。取消引用此指针是一个数组(类型为int [3]),而后者又可以衰减为指向其第一个元素的指针。

双解引用的作用是简单地取消引用两个指针,从而产生第一个数组的第一个元素,即x[0][0]

这恰好是3而不是1是因为您使用(1, 2, 3)初始化元素,而3正在使用逗号表达式,这导致{{ 1}}。

您可能想要做的是使用大括号作为“内部”数组:

unsigned int x[4][3] = {{1,2,3},{4,5,6},{7,8,9},{17,11,12}};

现在**x将导致1

要记住的另一件事是,对于任何数组或指针 x和索引i,表达式x[i]等于*(x + i)

答案 2 :(得分:1)

由于我认为是一个错字(使用括号而不是括号)这个声明

unsigned int x[4][3] = {(1,2,3),(4,5,6),(7,8,9),(17,11,12)};

相当于

unsigned int x[4][3] = { 3, 6, 9, 12 };

数组的所有其他元素都是零初始化的。

结果,数组看起来像是以下面的方式显式初始化

unsigned int x[4][3] = { { 3, 6, 9 }, { 12, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };

例如,这个表达式

(1,2,3)

是一个逗号运算符的表达式,它产生最后一个操作数的值。

来自C标准(6.5.17逗号操作员)

  

2逗号运算符的左操作数被计算为void   表达;它的评估与之间存在一个序列点   正确的操作数。 然后评估右操作数;该   结果有类型和值

考虑例如

unsigned int x = ( 1, 2, 3 );
printf( "x = %u\n", x );

要获得预期结果,您必须用括号替换括号。例如

unsigned int x[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {17,11,12} };