Статическое распределение памяти — распределяется ли оно последовательно?

Мне нужно знать, гарантировано ли для всех компиляторов, что &N == &N_neg[MAXN] в следующем коде.

int N_neg[MAXN], N[MAXN]; // defined in the global scope!
T<N> t; // so I can access N[i] (for i < 0) inside T

Если это так, я закончил, это все, что мне нужно. Если нет, пожалуйста, прочитайте мою полную проблему ниже.

НОТА: Это предназначено для программирования конкурсов только, так что не беспокойтесь о ремонтопригодности. Я больше обеспокоен сохранением T Легко понять.


У меня есть следующее определение:

template<int* B> class T { ... }

внутри TОднако я получаю доступ B[-n], где n > 0, Итак, вот что я хочу сделать:

#define MAXN 1000
int N[2*MAXN];
T<N + MAXN> t;

Это не разрешено, согласно компилятору. cppreference даже есть пример этого конкретного случая, говоря это не работа, и я уже искал решение повсюду в другом месте (пока ничего не найдено). Я понимаю, как работают шаблоны, и я знаю, что (и почему) значение каждого аргумента шаблона должно быть известно во время компиляции, а также адрес N известен только позже во время ссылки.

Какие-либо предложения?


Вот полный код (на тот случай, если у кого-то есть какие-либо предложения, основанные на проблеме):

template<int M, int B[]> struct Hash {
int h; Hash(int h = 0): h(h) {}
int disp(int i) { return B[i]; }
Hash concat(int ch, int i) { return (h + (ll) ch * B[i]) % M; }
Hash subtract(int hl, int i) { return (ll) (h - hl + M) * B[-i] % M; }
static void genBase(int n, int b) {
B[0] = 1, B[-1] = powlg(b, M-2, M); // b^(-1) % M = b^(M-2) % M
for (int i = 1; i < n; i++)
B[i] = (ll) B[i-1] * b % M, B[-i] = (ll)B[-i+1] * B[-1] % M;
}
};

-3

Решение

если это гарантировано, для всех компиляторов, что &N == &N_neg[MAXN]

Это абсолютно не гарантировано. Стандарт C ++ не предписывает относительное расположение в памяти переменных. На самом деле, это накладывает очень мало ограничений на расположение памяти в общем.

Технически даже не гарантируется, что N а также N_neg не будет оптимизирован компилятором в некоторых случаях (хотя взятие их адресов обычно предотвращает это).


Чтобы сделать макет последовательным, вы можете использовать структуру:

struct { int N_neg[MAXN], N[MAXN]; } arrays;

Затем, теоретически вы можете получить доступ N_neg[MAXN] в той же области памяти, что и N[0], Тем не мение, это неопределенное поведение! Это мог работать для вас, но скажем, вы назначаете N_neg[MAXN], Компилятор может предположить, что N[0] не мог быть изменен, и оптимизировал бы любой доступ к нему, заставляя вашу программу вести себя странно.

Вы можете обойти это в некоторой степени, объявив оба массива volatile, но тогда вы теряете кучу потенциальных оптимизаций.

Поэтому я бы очень неохотно использовал этот подход. Почти всегда лучше придерживаться определенного поведения.


Основываясь на обновленных / обнаруженных требованиях, вы получите близко нужно только один параметр шаблона:

template <typename T, T&>
struct Hash;

template <std::size_t Size, typename T, T (&Array)[Size]>
struct Hash<T[Size], Array>
{
// Your code here

private:
static constexpr T *N = &Array[Size / 2];
};

Установлено как это:

int N_backing[MAXN * 2];
Hash<decltype(N_backing), N_backing> hash;

Как N является constexprего значение гарантированно будет вычислено во время компиляции.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]