指向二维数组的指针(为什么起作用)

丹尼尔

我有以下功能(我想打印给定行中的所有元素)

void print_row(int j, int row_dimension, int *p)
{   
p = p + (j * row_dimension);

for(int i = 0; i< row_dimension; i++)
    cout<<*(p+i)<< " ";
}

创建一个数组

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

我不明白的是为什么我可以通过以下方式调用该函数:

print_row(i, 3, *j);

为什么可以给我一个参数“ * j”?地址不应该通过吗?为什么要使用间接运算符?

塞尔吉·巴莱斯塔(Serge Ballesta)

j实际上是一个数组数组。这样,它*j是一个由三个整数组成的数组,当用作右值时,它将衰减为指向其第一个元素的指针,换句话说,它将衰减为&j [0] [0]。

然后,在printrow计算每个子数组的第一个元素的起始地址时-这是不太好的部分,我稍后再讲。然后,您可以正确使用*(p+i)等价的p[i]来访问子数组的每个元素。


答案的其余部分是我对C标准的严格阅读的解释

我说过,计算每个子数组的起始地址不是那么好。之所以起作用,是因为我们都知道大小为NxM的2D数组在内存中的表示形式与大小为N * M的线性数组相同,因此我们将这些表示形式作为别名但是,如果我们严格遵守标准,则作为int指针,它&p[i][j]指向三个元素的数组中的第一个元素。这样,当您增加行的大小时,您将指向数组的末尾,如果您稍后取消引用该地址,则会导致未定义的行为。当然,它可以与所有常见的编译器一起使用,但是这是我的一个老问题,@ HansPassant给了我有关能够对数组大小执行控制的实验性编译器的参考。这些编译器可以检测到数组末尾的访问,并引发运行时错误……但是这会破坏很多现有代码!

为了严格符合标准,应使用一个指向3个整数的数组的指针。它要求使用可变长度数组,这是一项可选功能,但完全符合支持该功能的系统的标准。或者,您可以转到2D数组字节表示形式,获取其初始地址,然后从那里计算每个子数组的起点作为字节地址这是很多沸腾的地址计算,但它完全遵守@#!%$严格的别名规则...

TL / DR:此代码可用于所有常见的编译器,并且可能会与它们的许多将来版本一起使用,但是严格解释该标准并不正确。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

指向二维指针数组的指针

Typedef 指向二维数组的指针

为什么这个二维数组比较不起作用?

为什么当为一维数组重新分配指向 char 的指针时显示错误但二维数组工作正常?

为什么指向列表的指针创建二维列表结构

从C函数返回指向二维数组的指针

为什么指向数组表达式的指针起作用

为什么二维随机游走的一维变体不起作用?

二维指针数组

为什么对二维数组应用间接寻址会提供一个指针?

为什么在将双指针用作二维数组的参数时出现“分段错误”?

指针变量指向一维数组还是二维数组?

c ++函数创建一个二维数组并返回一个指向二维数组的指针

为什么C ++中auto_ptr的二维向量不起作用?

二维数组填充不起作用

更改二维数组变量也会更改原始二维数组变量。为什么?

声明一个指向二维数组指针的指针

如何将二维数组静态初始化为指向指针的指针?

指向二维数组的特定行

指向一维数组和二维数组有什么区别?

为什么二维数组的情况下可以从int **转换为int *,而指针数组的情况下不行

为什么要使用二维结构数组?

为什么将此Java数组视为二维的?

如何动态分配二维数组,为什么?

为什么我的二维数组不旋转?

为什么二维数组中的范围是这样写的?

为什么要创建二维数组-Excel VBA

用于取消引用指向固定大小二维数组的指针的 C typedef

指向二维数组中一行的可变指针