Расположение памяти глобалов

Рассматривать

Foo data[]={{...},{...},{...}};
Foo data_end={...};

Если маркер конца определен сразу после массива, гарантируется ли, что

&data[3]==&data_end

Я не хочу подсчитывать количество элементов в данных вручную.

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

0

Решение

Нет. Это не надежное предположение, что компилятор размещает переменные в любом порядке или любом выравнивании. Между переменными для выравнивания могут быть промежутки, и я уже видел компиляторы, которые упорядочивают переменные по алфавиту.

Если вы хотите знать указатель на элемент, который не в массиве нужно знать количество элементов массива.

#define _dimof(a) (sizeof(a)/sizeof(a[0]))
Foo data[] = ... ;
// The type of the variable has been changed.
Foo* data_end = &data[_dimof(data)];

Вы можете удалить этот абзац, так как он был добавлен, чтобы исправить синтаксическую ошибку в коде.

1

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

Не гарантируется не только то, что вы запрашиваете, но, кроме того, реализация, совместимая с C ++ 03 должен убедиться, что &data[3] != &data_end:

5.10 Операторы равенства [expr.eq]

1… Два указателя одного и того же типа сравниваются равными тогда и только тогда, когда они оба равны нулю, оба указывают на один и тот же объект или функцию или оба указывают один за концом одного и того же массива.

В C ++ 11 это немного сложнее:

Два указателя одного и того же типа сравниваются равными, если и только если они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес (3.9.2).

3.9.2 примечания:

… Если объект типа T находится по адресу Aуказатель типа резюме T* чьим значением является адрес A говорят, что он указывает на этот объект, независимо от того, как было получено значение. [Примечание: например, считается, что адрес, следующий за концом массива (5.7), указывает на несвязанный объект типа элемента массива, который может быть расположен по этому адресу. … — конец примечания]

Таким образом, новый стандарт позволяет может быть вывести правду в вашем сравнении; Тем не менее, нет никаких гарантий.

Если вам нужно посчитать количество элементов массива, используйте следующий макрос:

#define countof(ARR) (sizeof (ARR) / sizeof *(ARR))

Или, если вам не нравятся макросы, используйте следующую функцию:

template<class T, std::size_t N>
constexpr std::size_t countof(T (&)[N])
{
return N;
}

Последний вариант, однако, требует, чтобы ваш компилятор поддерживал constexpr Ключевое слово, чтобы быть полным функциональным эквивалентом первого.

4

Нет, это не надежно, в C ++ 11 просто сделайте

for (/* const */ Foo& foo : data) {
// stuff with foo.
}
0
По вопросам рекламы [email protected]