Я ищу 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 :
Когда выражение с целым типом добавляется или вычитается из указателя, результат имеет типоперанд указателя.Если выражение P указывает на элемент x [i] объекта массива x с n элементами, выражения P + J и J + P (где J имеет значение j) указывают на (возможно, гипотетический) элемент x [i +j] если 0 ≤ i + j ≤ n; в противном случае поведение не определено .Аналогично, выражение P - J указывает на (возможно, гипотетический) элемент x [i - j], если 0 ≤ 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
?(аналогично, при холодной выборке ссылок на массивы, мы должны иметь возможность просто получить указатель, не основанный на нуле, без выполнения вычислений, чтобы просто установить ссылку в регистрах)