Сложение указателя и вычитание в секте.6.5.6 - PullRequest
2 голосов
/ 25 ноября 2011

Я пытаюсь понять параграфы 8 и 9 C99, раздел 6.5.6 (Аддитивные операторы)

Означает ли пункт 8:

int a [4];

int *p = a;
p --;      /* undefined behaviour */

p = a + 4; /* okay */
p --;      /* okay */
p += 2;    /* undefined behaviour */

p = a;
p += 5 - 5;    /* okay */
p = p + 5 - 5; /* undefined behaviour */

Для параграфа 9 я понял, что ptrdiff_t всегда достаточно велик, чтобы содержать разницу в 2 указателя. Но формулировка: «при условии, что значение вписывается в объект типа ptrdiff_t», по-видимому, предполагает, что это понимание неверно. Мое понимание неверно, или C99 имел в виду что-то еще.

Вы можете найти ссылку на проекты стандартов здесь: http://cboard.cprogramming.com/c-programming/84349-c-draft-standards.html

Ответы [ 2 ]

2 голосов
/ 26 ноября 2011

Я не думаю, что ваша интерпретация верна. В версии у меня (n1256) параграф 9 гласит:

Если результат не может быть представлен в объекте этого типа, поведение не определено

вот и все. Если разница больше PRTDIFF_MAX или меньше PTRDIFF_MIN, поведение не определено.

Обратите внимание, что это накладывает бремя на программиста, чтобы проверить, соответствует ли разница в ptrdiff_t. «Ленивая» реализация платформы может просто выбрать узкий тип для ptrdiff_t и оставить вас в покое.

Проверка на это не будет прямой, так как вы не можете сделать вычитание, не провоцируя UB. Вам придется использовать информацию, указанную двумя указателями внутри (или чуть дальше) одного и того же объекта и где находятся границы этого окружающего объекта.

0 голосов
/ 25 ноября 2011

Я согласен с вашим пониманием пункта 8. Стандарт гласит

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

Кажется, что C предполагает, что в массиве нет переполнения указателей, поэтому вы можете увеличивать / уменьшать указатели, оставаясь внутри массива. Если указатель результата покидает массив, может произойти переполнение и поведение не определено.

Что касается параграфа 9, я полагаю, что стандарт учитывает, что вы, например, можете иметь архитектуру, которая предоставляет 32-битные указатели и 32-битные типы данных, но поскольку различие двух 32-битных указателей фактически является знаком плюс 32-битный (то есть 33 бита), не каждая разность указателей может совпадать с 32-битным ptrdiff_t. С архитектурой 2 дополнения это не проблема, но это может быть проблемой на других архитектурах.

...