Я, вероятно, неправильно понимаю это, но предотвращает ли спецификация c99 какую-либо форму арифметики с указателями на динамически выделяемой памяти?
С 6.5.6p7 ...
ДляВ целях этих операторов указатель на объект, который не является элементом массива, ведет себя так же, как указатель на первый элемент массива длиной один с типом объекта в качестве его типа элемента.
... указатель на объект не в массиве обрабатывается так, как если бы он указывал на массив из 1 элемента (при использовании операторов + и -).Тогда в этом фрагменте:
char *make_array (void) {
char *p = malloc(2*sizeof(*p));
p[0] = 1; // valid
p[1] = 2; // invalid ?
return p;
}
... второй индекс p[1]
недействителен?Поскольку p
указывает на объект не в массиве, он рассматривается как указывающий на объект в массиве из одного элемента, а затем из 6.5.6p8 ...
Когда выражение имеет целое числоТип добавляется или вычитается из указателя, результат имеет тип операнда указателя.Если операнд-указатель указывает на элемент объекта массива, и массив достаточно велик, результат указывает на смещение элемента от исходного элемента, так что разность индексов результирующего и исходного элементов массива равна целочисленному выражению.Другими словами, если выражение P указывает на i-й элемент объекта массива, выражения (P) + N (эквивалентно, N + (P)) и (P) -N (где N имеет значение n) указываютсоответственно i + n-м и i-n-м элементам массива, если они существуют.Кроме того, если выражение P указывает на последний элемент объекта массива, выражение (P) +1 указывает один за последним элементом объекта массива, а если выражение Q указывает на один последний элемент последнего элемента массива,выражение (Q) -1 указывает на последний элемент объекта массива.Если и операнд-указатель, и результат указывают на элементы одного и того же объекта массива или один после последнего элемента объекта массива, оценка не должна вызывать переполнение;в противном случае поведение не определено.Если результат указывает на один последний элемент массива, он не должен использоваться как операнд унарного * оцениваемого оператора.
... у нас неопределенное поведение, так как мы разыменовываемза границей массива (тот, который имеет длину 1).
Редактировать:
ОК, чтобы попытаться объяснить больше, что меня смущает, давайте сделаем это шаг за шагом:
1.) p[1]
определяется как означающее *(p+1)
.
2.) p
указывает на объект, который не находится внутри массива, поэтому он обрабатывается так, как если бы он указывал на объектвнутри массива длины 1 с целью оценки p+1
.
3.) p+1
создает указатель 1 после массива, на который подразумевается p.
4.) *(p+1)
выполняетнедопустимая разыменование.