Безопасна ли арифметика указателей в итерациях при переполнении?

Я очень часто видел итерации массива с использованием простой арифметики указателей даже в более новом коде C++. Интересно, насколько они безопасны на самом деле, и стоит ли их использовать. Рассмотрим этот фрагмент (он также компилируется в C, если вы calloc на месте new):

int8_t *buffer = new int8_t[16];
for (int8_t *p = buffer; p < buffer + 16; p++) {
    ...
}

Не приведет ли этот тип итерации к переполнению и пропаданию цикла полностью, когда buffer случается распределяется по адресу 0xFFFFFFF0 (в 32-битном адресном пространстве) или 0xFFFFFFFFFFFFFFF0 (64 бит)? Насколько я знаю, это будет исключительно неудачное, но все же возможное обстоятельство.

1 ответ

Это безопасно. Стандарты C и C++ явно позволяют вычислять значение указателя, которое указывает на один элемент за концом массива, и сравнивать указатель, который указывает в массиве, с этим значением.

Реализация, которая имела проблему переполнения в описываемой вами ситуации, просто не имела бы права помещать массив прямо в конец памяти, как этот.

На практике более вероятная проблема buffer + 16 Сравнение равно NULL, но это недопустимо, и соответствующая реализация должна оставить пустое место после конца массива.

Другие вопросы по тегам