我正在寻找 gcc 支持的 C++ 语言扩展来启用非从零开始的数组指针的分配。理想情况下我可以简单地写:
#include<iostream>
using namespace std;
// Allocate elements array[lo..hi-1], and return the new array.
template<typename Elem>
Elem* Create_Array(int lo, int hi)
{
return new Elem[hi-lo] - lo;
// FIXME what about [expr.add]/4.
// How do we create a pointer outside the array bounds?
}
// Deallocate an array previously allocated via Create_Array.
template<typename Elem>
void Destroy_Array(Elem* array, int lo, int hi)
{
delete[](array + lo);
}
int main()
{
const int LO = 1000000000;
const int HI = LO + 10;
int* array = Create_Array<int>(LO, HI);
for (int i=LO; i<HI; i++)
array[i] = i;
for (int i=LO; i<HI; i++)
cout << array[i] << "\n";
Destroy_Array(array, LO, HI);
}
上面的代码似乎可以工作,但不是由 C++ 标准定义的。具体来说,问题是[expr.add]/4 https://timsong-cpp.github.io/cppwp/n4659/expr.add#4:
对整型表达式进行加减运算时
对于指针,结果具有指针操作数的类型。如果
表达式 P 指向带有 n 的数组对象 x 的元素 x[i]
元素,表达式 P + J 和 J + P(其中 J 的值为 j)
如果 0 ≤ i + j ≤ 则指向(可能是假设的)元素 x[i + j]
n;否则,行为是未定义的。同样,表达式 P -
如果 0 ≤ i − j,J 指向(可能假设的)元素 x[i − j]
≤ n;否则,行为是未定义的。
换句话说,上面代码中标记为 FIXME 的行的行为未定义,因为它计算的指针超出了范围x[0..n]
对于从 0 开始的数组x
.
有没有一些--std=...
选项gcc
告诉它允许直接计算非从零开始的数组指针?
如果没有,是否有一种合理可移植的方式来模拟return new Type[hi-lo] - lo;
声明,也许通过转换为long
然后回来? (但我会担心引入更多错误)
此外,是否可以通过仅需要 1 个寄存器来跟踪每个数组的方式来完成此操作,如上面的代码?例如,如果我有array1[i], array2[i], array3[i]
这只需要数组指针的 3 个寄存器array1, array2, array3
,加上一个注册i
? (类似地,如果冷获取数组引用,我们应该能够直接获取非零基指针,而无需进行计算以在寄存器中建立引用)