c语言 - ** 如何在二维数组中工作?


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。 当 x 存储数组第一个元素的地址时,它不应该是 1,4,7,17 吗?

当我尝试打印时

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 

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

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] = {{1,2,3},{4,5,6},{7,8,9},{17,11,12}};

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

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

双重取消引用所做的只是取消引用两个指针,从而产生第一个数组的第一个元素,即x[0][0].

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

您可能还想对"内部"数组使用大括号:

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)

由于我认为拼写错误(使用括号而不是大括号)此声明

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 = %un", x );

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

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

最新更新