是 C 样式数组到 std::array 转换对于数组完全安全
Is a C-Style array to std::array transition completely safe for arrays?
第一次提问者:)是否可以在不破坏代码的情况下将全局 c 样式数组转换为 std::arrays?我正在做一个项目,其中包括反编译旧游戏的源代码。我们已经设法重构了大部分反汇编/反编译输出。由于它是自动的,因此仍然有这样的部分
int a;
int b[50];
*(&a + 100) = xxx;
或
int b[50];
int a;
*(&a - 100) = xxx;
以及其他类型的疯狂指针算法,尚未手动重构。但是我们想对(大概(正确更改为数组的部分使用边界检查。
(忽略斜体文本,我保留它只是为了评论的一致性(到目前为止,我发现追逐每个数组存在一个问题:sizeof(class containing array)
会改变。例如,这可能会在某些周期中破坏代码 某类某阵列[100]; 例如 (sizeof(somearray[0]( == 50( 为真 int 指针 = (int(somearray; 指针 += 100 ((someclass(pointer(->doSomething((;.因为pointer +=100
不会指向第二个元素,而是指向第一个元素中的某个地方,甚至是零元素,我不确定(不要忘记它是自动反编译的代码,因此很丑陋(。
我正在考虑将每个全局数组更改为 std::array 以及访问数组的每个实例而无需[]
运算符来array._Elems
。
如果我在这样的代码中将全局数组更改为 std::arrays,是否可能会出现任何问题?
编辑你对大小不变是对的。我在测试功能中遇到错误。所以我将扩展这个问题:
将每个 c 样式数组更改为 std::array 是否安全?
编辑我们当前的代码实际上只能在调试模式下运行,因为它不会移动变量。发布模式基本上在程序开始时崩溃。
编辑由于这个问题似乎有些混乱,让我澄清一下:除了 T elems [N] 之外,是否可以保证数组中没有其他成员?我可以指望拥有吗
array<array<int,10>, 10> varname;
int* ptr = &varname[0][0];
ptr += 10
并确保 PTR 指向varname[1][0]
,而不管实施细节如何?虽然可以保证数组是连续的,但我不确定这一点。该标准包含一个实现,但我不确定这是一个示例实现还是每个实现都应该遵循迭代器的实际定义,const_iterator是唯一特定于实现的东西,因为只有那些有词实现定义(我手头没有最新的规范,所以可能还有其他一些差异(。
对于一维数组,这可能适用于所有情况,2D 情况更棘手:
原则上,std::array <>模板可以只包含数组本身,因为它的长度参数是一个不需要存储的编译时变量。但是,您的 STL 实现可能已经选择存储它或它需要的任何其他数据。因此,虽然 '&a[n
] == &a[0] + n' 适用于任何 std::array,但表达式 '&a[n][0] == &a[0][0] + n*arrayWidth' 可能不适用于 'std::array <std::array,>'。您可能仍然想检查 'sizeof(std::array <int,>( == sizeof(int( * 100' 与你的 STL 实现。如果是这样,即使是 2D 阵列也应该是安全的。
我想知道该替换应该如何在充满指针算术的代码中工作。
/// @file array_eval.cpp
#include <iostream>
#include <array>
#include <algorithm>
int main() {
auto dump = [](const int& n){std::cout << n << " ";};
#ifdef DO_FAIL
std::array<int, 10> arr;
#else
int arr[10];
#endif
// this does not work for std::arrays
int* p = arr;
std::for_each(p, p+10, dump);
std::cout << std::endl;
return 0;
}
和
g++ -Wall -pedantic -std=c++11 -DDO_FAIL array_eval.cpp
当然失败了:
array_eval.cpp: In function ‘int main()’:
array_eval.cpp:17:14: error: cannot convert ‘std::array<int, 10ul>’ to ‘int*’ in initialization
int* p = arr;
^
这取决于 STL 实现。我的意思是,该标准不会阻止使用更多成员来实现std::array
,或者保留更多内存确实是必要的(例如,用于调试(,但我认为在不使用更多数据成员的情况下找到一个std::array
实现是非常不可能T elem[N];
。
如果我们假设 std::array 实现只包含一个用于存储数据的字段,并且它只分配必要的内存(而不是更多(,int v[100];
和数据存储的位置array<int, 100> v;
将具有相同的布局,因为从标准:
[阵列概述 23.3.2.1 p1]:
数组的元素是连续存储的,这意味着如果
a
一个array<T, N>
然后它服从所有0 <= n < N
的身份&a[n] == &a[0] + n
。
和 [class.mem 9.2 p20]:
指向标准布局结构对象的指针,使用
reinterpret_cast
指向其初始成员(或者如果该成员是 位域,然后是它所在的单元(,反之亦然。[ 注意:因此,在 标准布局结构对象,但不是在其开头,根据需要 以实现适当的对齐。—尾注 ]
无论如何,这取决于编译器和 STL 实现。但是反向代码也取决于编译器。为什么假设int a; int b[50];
将按该顺序在内存中定位a
然后b
数组,如果该声明不是struct
或class
的一部分,则不会在另一个顺序中定位?出于性能原因,编译器会决定其他事情(但我认为这不太可能(。
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 如何将元素添加到数组的线程安全函数?
- 将对象的字节复制到数组并再次复制回来是否安全
- 适用于大型数组的无复制线程安全环形缓冲区
- 问:Apache Arrow 数组生成器不安全追加
- 线程安全整数数组?
- 将积分类型的数组作为另一个不相关的积分类型的阵列进行访问的安全且符合标准的方法
- 使用字节数组具有单字节对齐方式的结构是否安全
- 在字节数组上转换具有虚函数的结构是否安全?
- 从 C# 到C++和返回的数组,没有不安全的代码
- 将整数添加到数组值而无需调用它的最安全方法
- 我可以使用模板作为多态处理数组的安全解决方案
- 静态指针指向会员数组的安全操作员[]访问
- 在固定的,无序的,拥有的数组中安全,惯用的销毁和压缩
- 在 c++ 的多个线程中编写 c 数组的不同项是否线程安全
- 标准::数组是否可安全返回
- 当结构数组在主线程中填充数据时,从结构数组的低索引元素读取是否线程安全
- 在多线程程序中使用动态数组的头段安全吗
- 当使用来自不同类的字符数组是安全的时
- 当需要数组时,将指针传递到向量中的第一个元素是否安全