Почему добавление к указателю с + = работает, но указатель + 1 не работает?
Я выделяю память для массива, но я перемещаюсь туда, где указатель немного указывает вперед. Доступ к элементам работает нормально. Однако он начал создавать проблему с освобождением выделенной памяти. Malloc жалуется, что освобожденный указатель никогда не выделялся. Проблема может быть воспроизведена с помощью этого упрощенного кода:
int *pointer = malloc(sizeof(int)) + 1;
free(pointer - 1);
Я начал экспериментировать и нашел это небольшое изменение кода для работы.
int *pointer = malloc(sizeof(int));
pointer += 1;
free(pointer - 1);
Что такое + = выполнение отличается от простого добавления 1 в указатель malloc возвращает в одной строке?
Ответы
Ответ 1
Возвращаемым типом malloc
является void *
, который, согласно стандарту, не может использоваться для арифметики указателя.
Однако существует расширение GNU, которое обрабатывает sizeof(void)
как 1
, и поэтому ваш первый фрагмент компилируется. Позже pointer - 1
вычитает sizeof(int)
, а не 1
, следовательно, несоответствие указателя.
Фактические смещения, применяемые при выполнении арифметики указателя, всегда зависят от типа указателя. Поскольку pointer
есть int *
, фактические смещения будут умножаться на sizeof(int)
. Если sizeof(void)
- 1
или если это a char *
указатель (sizeof(char) == 1
), то никакого умножения не происходит.
Ответ 2
Арифметика указателя может быть выполнена с использованием любого из +
или +=
. Это не имеет ничего общего с созданной ошибкой.
malloc
возвращает тип void *
. C говорит, что:
C11: 6.2.5 Типы (p19):
Тип void
содержит пустой набор значений; это неполный тип, который не может быть завершен.
6.5.6 Аддитивные операторы (p2):
Для добавления оба операнда должны иметь арифметический тип, или один операнд должен быть указателем на полный тип объекта, а другой должен иметь целочисленный тип. (Инкремент эквивалентен добавлению 1.)
void *
- указатель на неполный тип. Следовательно, с типом void *
никакого добавления не будет. Вот почему
int *pointer = malloc(sizeof(int)) + 1;
неверно и приведет к ошибке времени выполнения при выполнении free(pointer - 1);
.
Ответ 3
Выбрали другие ответы, измените свой код на
int *pointer = (int *)malloc(sizeof(int));
или
int * pointer = new int[1];
позволит вам делать то, что вы хотели.