Рассматривать
Foo data[]={{...},{...},{...}};
Foo data_end={...};
Если маркер конца определен сразу после массива, гарантируется ли, что
&data[3]==&data_end
Я не хочу подсчитывать количество элементов в данных вручную.
В GDB все выглядит нормально, без какой-либо опции оптимизации, но прежде чем использовать его, я должен знать, что компилятор не может двигаться data_end
, Если это возможно, как я могу сделать вместо этого.
Нет. Это не надежное предположение, что компилятор размещает переменные в любом порядке или любом выравнивании. Между переменными для выравнивания могут быть промежутки, и я уже видел компиляторы, которые упорядочивают переменные по алфавиту.
Если вы хотите знать указатель на элемент, который не в массиве нужно знать количество элементов массива.
#define _dimof(a) (sizeof(a)/sizeof(a[0]))
Foo data[] = ... ;
// The type of the variable has been changed.
Foo* data_end = &data[_dimof(data)];
Вы можете удалить этот абзац, так как он был добавлен, чтобы исправить синтаксическую ошибку в коде.
Не гарантируется не только то, что вы запрашиваете, но, кроме того, реализация, совместимая с 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
Ключевое слово, чтобы быть полным функциональным эквивалентом первого.
Нет, это не надежно, в C ++ 11 просто сделайте
for (/* const */ Foo& foo : data) {
// stuff with foo.
}