这是可移植C++代码吗?(假设多维数组具有连续的内存布局)



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

我的问题是,当我们有一个二维数组时,如果我是对的,从计算机和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;
}

标准语

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

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]这样的东西做同样的事情并且保证可移植。

如果你想真正严格,reinterpret_cast在标准中并没有很好的定义。这在任何地方都有效,但你可以对它提出一个迂腐的理由。

int *ptr = arr[0];

为了非常安全。保证连续阵列布局。

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

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

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

最新更新