Почему добавление к указателю с + = работает, но указатель + 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];

позволит вам делать то, что вы хотели.