Двойной указатель в c, предупреждение о назначении для моего кода

Я не знаю, почему я получаю предупреждения для следующего кода.

#include<stdio.h>
#include<malloc.h>
int main()
{
    int **p;
    int i,j;
    for(i=0;i<5;i++)
    {
        if(i==0)
            p=(int*)malloc(1*sizeof(int));
        else
            p=(int*)realloc(p,(i+1)*sizeof(int));
        p[i]=(int*)malloc(5*sizeof(int));

        for(j=0;j<5;j++)
        {
           p[i][j]=j;
        }
    }
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
            printf("%5d",p[i][j]);
        printf("\n");
    }

    return 0;
}  

Есть ли другой способ динамического выделения памяти для двойного указателя.


person Sashank Alladi    schedule 30.08.2013    source источник
comment
Можете ли вы показать предупреждающие сообщения?   -  person krsteeve    schedule 30.08.2013
comment
@Sashank, что ты пытаешься сделать с этим кодом?   -  person Eric Z    schedule 30.08.2013
comment
почему вы используете динамическое распределение p для начала? Почему не int *p[5];?   -  person Ben Voigt    schedule 30.08.2013
comment
@EricZ Я пытаюсь реализовать демонстрационную программу, вставляя значения в двумерный массив, который создается путем динамического выделения памяти.   -  person Sashank Alladi    schedule 30.08.2013
comment
@BenVoigt, я пытаюсь использовать двойной указатель, почему двойной указатель, потому что фрагмент, в котором вы указали int *p[5], вы должны указать значение, т.е. количество строк, что, если вы не знаете, сколько строк вы собираетесь создать.   -  person Sashank Alladi    schedule 30.08.2013
comment
@SashankAlladi: Ну, 5 было жестко закодировано в вашей программе, поэтому я думал, что вы знали это заранее. Если вы не знаете, пока после нескольких итераций, то я согласен.   -  person Ben Voigt    schedule 30.08.2013
comment
@BenVoigt Я тебя понял, программа всего лишь демо, ну, это моя вина, я должен явно указать это.   -  person Sashank Alladi    schedule 31.08.2013


Ответы (3)


Это компилируется без предупреждения

  int **p;
  p = (int **) malloc(sizeof(void *));
person stark    schedule 30.08.2013
comment
Какой компилятор вернет размер void*, отличный от int**? - person stark; 31.08.2013
comment
Эти примеры С++ - person stark; 31.08.2013
comment
Так? C++ предоставляет те же гарантии для примитивных типов, что и C. Размер указателя определяется платформой, а не языком. (Вы можете вытащить правило из стандарта C, которое говорит об обратном... но я не думаю, что оно существует) - person Ben Voigt; 31.08.2013
comment
Только что проверил стандарт C. Раздел 6.2.5/26 является соответствующим правилом и прямо говорит, что void* не обязательно должен быть того же размера, что и любой другой указатель, кроме char*. - person Ben Voigt; 31.08.2013
comment
malloc возвращает нетипизированный тип void *, и вы приводите его к нужному типу указателя. Как это будет работать с разными размерами указателя? - person stark; 31.08.2013
comment
Попробуйте на самом деле прочитать объяснения, на которые я ссылался. Краткая версия: void* должен содержать любой адрес, int* должен содержать только выровненные адреса, что означает меньше информации. - person Ben Voigt; 31.08.2013
comment
Поскольку у вас было достаточно возможностей исправить свой ответ, но вы продолжали распространять неправильный код, вы получили от меня -1. - person Ben Voigt; 31.08.2013

Вы получаете предупреждения, потому что p — это int **, и вы выделяете память, как если бы это было int * в ваших if..else строках. Просто замените строки следующим образом:

p=(int **)malloc(1*sizeof(int *));

p=(int **)realloc(p,(i+1)*sizeof(int *));
person trogdor    schedule 30.08.2013

Вы получаете предупреждения, поскольку (а) приводите возвращаемое значение malloc() и realloc() и (б) приводите его к неправильному типу. В C обычно считается, что лучше вообще не приводить возвращаемое значение malloc() и realloc(), потому что void* автоматически преобразуется в любой другой тип указателя, а добавление ненужного приведения может привести к ошибкам (например, к вашим).

person This isn't my real name    schedule 30.08.2013