Безопасна ли арифметика указателей в итерациях при переполнении?
Я очень часто видел итерации массива с использованием простой арифметики указателей даже в более новом коде 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
, но это недопустимо, и соответствующая реализация должна оставить пустое место после конца массива.