realloc не копирует первый индекс

У меня возникли проблемы с использованием команды malloc/realloc с массивами. Я создал небольшой массив с некоторыми целыми числами и попытался добавить к нему одно значение, увеличив размер с помощью realloc и добавив значение, но когда я это делаю, значение индекса 0 не сохраняется и рассматривается как мусор.

#include <stdio.h>
#include <stdlib.h>

int main(){
        int n;
        printf("Enter size of array\n");
        scanf("%d",&n);
        int *A = malloc(n*sizeof(int));
        for(int i = 0; i < n; i++){
                A[i] = i + 1;
        }
        *A = realloc(A, sizeof(A)+ sizeof(int));
        A[n] = 1234;
        for(int i = 0; i < n + 1; i++){
                printf("%d\n",A[i]);
        }


        return 0;
}

и когда я запускаю программу, это происходит:

Enter size of array
5
14643216
2
3
4
5
1234

Кто-нибудь знает, почему индекс 0 массива получает это значение, а не 1?


person Nathan Kennedy    schedule 13.03.2018    source источник
comment
*A = realloc(A — ерунда как с точки зрения времени выполнения, так и с точки зрения типа. Вы говорите, перераспределите A, получив новый указатель. Затем сохраните этот указатель в первый элемент старого A (который может совпадать или не совпадать с новым A). *A имеет тип int, поэтому вы должны увидеть диагностическое сообщение о том, что возвращаемый тип void * из realloc преобразуется в int без приведения.   -  person Kaz    schedule 14.03.2018
comment
A — это переменная типа указателя, *A — это значение, на которое указывает указатель A, в данном случае — первый элемент массива. Таким образом, изменение *A фактически меняет первый элемент этого массива, а не сам указатель.   -  person Havenard    schedule 14.03.2018
comment
В malloc это работает, потому что * интерпретируется не как модификатор A, а как модификатор типа, поскольку вы объявляете его в той же строке.   -  person Havenard    schedule 14.03.2018
comment
... и sizeof (A) - это размер типа указателя, а не старый размер массива.   -  person Lee Daniel Crocker    schedule 14.03.2018


Ответы (2)


$ gcc a.c
a.c: In function ‘main’:
a.c:12:12: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
         *A = realloc(A, sizeof(A)+ sizeof(int));
            ^

Обязательно настройте свой компилятор на выдачу предупреждений о коде, который выглядит подозрительно. Любой хоть сколько-нибудь приличный компилятор выдаст в этой строке как минимум предупреждение, если не ошибку. realloc возвращает указатель, который вы пытаетесь присвоить объекту int.

Полученный указатель нужно присвоить A, а не *A. Кроме того, есть еще одна ошибка, о которой компиляторы не могут вас предупредить. sizeof(A)+ sizeof(int) слишком маленькое и не имеет особого смысла в контексте. Обратите внимание, что sizeof(A) — это размер указателя A. Невозможно использовать sizeof для поиска количества элементов в массиве, на которое указывает A, потому что sizeof полагается на информацию времени компиляции. Чтобы расширить массив на один элемент, вам нужно добавить sizeof(int) к текущему выделенному размеру, который равен n*sizeof(int), т.е. новый размер должен быть (n+1) * sizeof(int).

Кроме того, было бы лучше использовать sizeof(*A), чем sizeof(int). Они эквивалентны, но sizeof(*A) имеет то преимущество, что оно все равно будет правильным, если вы решите изменить элементы массива, например. чтобы сделать их long.

A = realloc(A, (n+1) * sizeof(*A));
person Gilles 'SO- stop being evil'    schedule 13.03.2018
comment
Благодарю вас! Это было очень полезно. Указатели и выделение памяти для начинающих настолько пугают, и это очень помогает! - person Nathan Kennedy; 14.03.2018

Пишите A = realloc(A, (n + 1) * sizeof(int)); вместо *A = realloc(A, sizeof(A)+ sizeof(int));

*A = ... перезапишет значение первого индекса «значением адреса», если A не будет перемещено в другое место в памяти (в противном случае поведение undefined).

Обратите внимание, что sizeof(A) — это постоянное значение (вероятно, 8, а не объем выделенной ранее памяти), так что у вас был хороший шанс, что realloc не переместит память.

person Stephan Lechner    schedule 13.03.2018
comment
Нет. Должно быть A = realloc(A, (n + 1) * sizeof(int)). Предполагается, что он добавляет дополнительный элемент в динамически выделяемый массив. - person davmac; 14.03.2018