Правильные ответы были даны много лет назад, но мне интересно, что C99 обоснование [сек. 6.5.6, последние 3 абзаца] объясняет, почему стандарт поддерживает добавление 1
к указателю, который указывает на последний элемент массива (p+1
):
Важным подтверждением широко распространенной практики является требование о том, что указатель всегда можно увеличивать до конца массива, не опасаясь переполнения или переноса
и почему p-1
не подтверждено:
В случае p-1, с другой стороны, весь объект должен быть размещен до массива объектов, через которые проходит p, поэтому декрементные циклы, которые выходят за пределы массива, могут потерпеть неудачу. Это ограничение позволяет сегментным архитектурам, например, размещать объекты в начале диапазона адресуемой памяти.
Таким образом, если указатель p
указывает на объект в начале диапазона адресуемой памяти, что подтверждается этим комментарием, то p-1
приведет к потере данных.
Обратите внимание, что целочисленное переполнение является примером стандарта для неопределенного поведения [сек. 3.4.3], так как это зависит от среды перевода и операционной среды. Я полагаю, что легко увидеть, что эта зависимость от среды распространяется на недостаточное указание.
Вот почему стандарт явно делает его неопределенным поведением [в 6.5.6 / 8], как отмечено другими ответами здесь. Чтобы процитировать это предложение:
Если и операнд-указатель, и результат указывают на элементы одного и того же объекта массива или один после последнего элемента объекта массива, при оценке не должно быть переполнения; в противном случае поведение не определено.
См. Также [с. 6.3.2.3, последние 4 абзаца] обоснования C99, в котором дается более подробное описание того, как недействительные указатели могут быть сгенерированы, и какие эффекты это может иметь.