2014-10-29 2 views
-2

Я застрял в компиляции двумерного массива в C, используя malloc();Динамически распределенная двумерная матрица в C

Попытки скомпилировать мой код в Microsoft Visual Studio Express 2013 я получаю ошибку «значение типа„Int **“не может быть отнесен к объекту типа„Int *“»

Вот мой код :

int main() { 
    int lines = 0; 
    int **cord; 

    FILE *f = fopen("data.txt", "r"); 
    if (f == NULL) return 0; 

    fscanf(f, "%d", &lines); 
    printf("%d", lines); 

    *cord = (int**)malloc(lines*sizeof(int*)); 

    int i = 0; 
    for (i; i < lines; ++i) 
    { 
     cord[i] = (int*)malloc(2 * sizeof(int)); 
     fscanf(f, "%d", cord[i][0]); 
     fscanf(f, "%d", cord[i][1]); 
    } 
    i = 0; 
    return 0; 
} 

Может ли кто-нибудь указать мне, что там не так?

+2

В C не выдавать результат 'malloc', а * всегда проверять * на отказ от' malloc'; также разрешить все предупреждения и информацию об отладке. –

+0

Это не 2D-массив, а только эмуляция. Вы можете определить и инициализировать свой массив одним вызовом 'malloc' как' int (* cord) [2] = malloc (2 * lines * sizeof (int)); '. –

ответ

1
*cord = (int**)malloc(lines*sizeof(int*)); 

переменная cord имеет тип int **, поэтому выражение *cord имеет тип int *. Вы делаете результат от malloc до int **. Таким образом, вы пытаетесь присвоить значение типа int ** выражению типа int *, что является ошибкой.Эта строка должна быть записана как

cord = malloc(lines * sizeof *cord); // note no cast, operand of sizeof 

Заметка стиля - пробел - ваш друг. Используй это. Твоим глазам не будет 20 лет навсегда.

Если число столбцов известно во время компиляции (как представляется, в данном случае), вы можете сделать выделение на один шаг:

int (*cord)[2]; 
... 
cord = malloc(lines * sizeof *cord); 
if (cord) 
{ 
    for (int i = 0; i < lines; i++) 
    { 
    fscanf(f, "%d", &cord[i][0]); 
    fscanf(f, "%d", &cord[i][1]); 
    } 
    ... 
    free(cord); 
} 
else 
    // handle allocation failure 

Переменная cord имеет тип «указатель на 2 -элементный массив int ", поэтому выражение *cord имеет тип" 2-элементный массив int ". sizeof *cord дает нам количество байтов, необходимых для каждого подмассива, поэтому lines * sizeof *cord дает нам общее количество байтов, необходимых для всего 2D-массива.

Преимущества - одноступенчатое распределение (что означает одношаговое освобождение), и все строки в массиве смежны.

Недостатков - Может потерпеть неудачу по очень большим массивам, если память достаточно фрагментирована, требует, чтобы вы знаете, число столбцов во время компиляции, или что ваш компилятор поддерживает массивы переменной длины (которые были введены в C99 и не являются обязательными, как от C2011).

В общем, ваши malloc заявления должны быть записаны в виде

T *ptr = malloc(N * sizeof *ptr); // calloc(N, sizeof *ptr) 

или

T *ptr = NULL; 
... 
ptr = malloc(N * sizeof *ptr); // calloc(N, sizeof *ptr); 

C не требует от вас, чтобы бросить результат malloc/calloc . C++ требует, так как он не позволяет неявное преобразование указателей void, но если вы пишете C++, вы должны использовать new и delete вместо malloc и free.


1. По состоянию на стандарт 1989 года, во всяком случае; до C89, malloc и calloc возвращено char * вместо void *, поэтому для составителей pre-C89 отливка была. MSVC поддерживает стандарт C89, поэтому вам не нужен литье

2

Во-первых, НЕ лить возвращаемое значение malloc().

Относительно ошибки в вашем коде сначала вам необходимо выделить память cord, затем cord[i] (или *cord).

Вместо использования

*cord = malloc(lines*sizeof(int*));,

использование

cord = malloc(lines*sizeof(int*));

Кроме того, добавить NULL чек на успех malloc(), как

if (!cord) //also for cord[i] 
{ 
    //print error and return/exit; 
} 
0

Изменение

*cord = (int**)malloc(lines*sizeof(int*)); 

в

cord = malloc(lines*sizeof(int*)); 

Кроме того, вы не выделяя 2D массив, а указатель на основе таблицы поиска. Чтобы выделить реальный 2D-массив, сделайте like this.

2
*cord = (int**)malloc(lines*sizeof(int*)); 

неправильно, вы разыменования неинициализированный указатель cord. Пожалуйста закодировать

cord = malloc(lines*sizeof(int*)); 
if (!cord) { perror("malloc cord"); exit (EXIT_FAILURE); } 

Никогда не забывайте проверять на провал malloc (вы должны также проверить его при назначении cord[i])

BTW, вы должны включить все предупреждения и отладочную информацию в вашем компиляторе. Если вы используете последнее GCC как gcc -Wall -Wextra -g, вас предупредили бы о первой ошибке.

Кроме того, если вы хотите получить матрицу в C, лучше использовать одномерный массив для ее представления.

Смежные вопросы