19

首先,如果我犯了任何语法错误等,对不起我的英语......

我的问题是,当我们有一个二维数组时,如果我是对的,从计算机和 C/C++ 的角度来看,它只是一个长的一维数组,索引只是帮助编译器映射到具体地址。

此代码片段在 Visual C++ 中工作,但我想知道,此代码是否移植符合 标准(C++98),不会对其他架构和/或操作系统造成意外:

int arr[][3] = { 1, 5, 3, 7, 5, 2, 7, 8, 9 };
const int ARR_NUM = sizeof(arr) / sizeof(int);

int* ptr = reinterpret_cast<int*>(arr);    // NOT: int(*)[][3] !!!
for (int i = 0; i < ARR_NUM; ++i) {
    cout << ptr[i] << endl;
}
4

4 回答 4

15

标准话

多维数组的元素按行优先顺序存储,因此手动索引是可移植的:

C++98、8.3.4/1:

数组类型的对象包含一个连续分配的非空集合,由 N 个类型为 T 的子对象组成。

显然,对于多维数组,这递归地适用。

然而,这种使用reinterpret_cast是不可移植的。标准说 (C++98, 5.2.10/1)

[...] 否则,结果是一个右值,并且 [...]、数组到指针、[...] 标准转换在表达式 v 上执行。

换句话说,传递arr立即触发数组衰减到指向其第一个元素的指针。然后 (C++98, 5.2.10/3) 来了

执行的映射reinterpret_cast是实现定义的。

本节的其余部分列出了一些例外情况,指定了总是明确定义的强制转换。鉴于它们都不适用于这里,因此结论是技术上它是默认实现定义的。

定论

从理论上讲,这不是便携式的。实际上,只要架构相同(例如 x86),我当然希望演员能够可靠地工作。

幸运的是,您不必假设这样的事情,因为正如其他 人提到的那样,类似的东西int* ptr = arr[0]做同样的事情并且保证便携。

于 2012-05-16T12:46:45.830 回答
4

如果您想非常严格,则 reinterpret_cast 在标准中的定义不是很好。这将适用于任何地方,但你可以提出一个迂腐的理由来反对它。

采用

int *ptr = arr[0];

为了安全起见。保证了连续的阵列布局。

于 2012-05-16T12:49:52.073 回答
0

至于假设,多维数组具有连续的内存布局,它符合标准且可移植。自 C 时代以来就是如此,C++ 并没有改变这一点。

但是,reinterpret_cast它不是可移植的,因此总体而言,不能保证您的代码在任何地方都可以工作。

于 2012-05-16T12:32:43.913 回答
0

如果我没记错reinterpret_cast的话不是便携操作。

于 2012-05-16T12:39:26.813 回答