Подтвердить что ты не робот

Ошибка компиляции Malloc: значение типа "int" не может использоваться для инициализации объекта типа int (*) [30]

Я должен был попробовать 20 способов сделать это. Мне действительно нужна помощь, независимо от того, что я делаю, я получаю ошибку, подобную этой.

a value of type "int" cannot be used to initialize an entity of type "int (*)[30]"

то есть. это вызовет мне такую ​​ошибку

int(*array)[160] = malloc((sizeof *array) * 10);

и делать что-то вроде этого

int** Make2DintArray(int arraySizeX, int arraySizeY) {
    int** theArray;
    theArray = (int**) malloc(arraySizeX*sizeof(int*));
    int i;
    for (i = 0; i < arraySizeX; i++)
    {
        theArray[i] = (int*) malloc(arraySizeY*sizeof(int));
    }
    return theArray;
}

получит мне это

"void *(size_t)" in "memory.c" at line 239 and: "int()" 

есть ли у кого-нибудь решение, как успешно выделить 2dArray из int [160] [10]

4b9b3361

Ответ 1

Оба эти компилируются для меня. Первая ошибка распространена, когда вы забываете #include <stdlib.h> до использования функций, объявленных внутри упомянутых (таких как malloc(size_t)), что я и не забыл сделать.

C имеет некоторое интересное поведение во время компиляции, в том числе возможность вызывать функцию, которая никогда не просматривалась (ни определение прототипа, ни реализация). Когда встречается такой вызов, C предполагает, что функция:

  • Что-то, что возвращает int
  • Принимает неизвестное количество аргументов, поэтому вызывающий может передать все, что захочет (включая неправильные вещи).

Напр., функция неявно предполагается, что она имеет вид:

int func();

Часто вы даже не заметите, за исключением предупреждений от вашего компилятора, которые сообщают о чем-то:

Warning: implicit declaration of `func` assumed to return `int`

и если вы находитесь на шаре, у вас есть уровни предупреждений, с включенными предупреждениями-как-то и поймать это.

Но что, если вы этого не сделаете? И что, если "вещь", возвращаемая функцией, не может быть представлена ​​содержимым размером данных в реализации int? Что, если, например, int были 32-битными, но указатели данных были 64-битными? Например, допустим, что char *get_str() объявлен в некотором заголовочном файле, который вы не включаете, и реализован в файле .c, который вы компилируете и связываете с вашей программой, который выглядит следующим образом:

#include <stdio.h>

// Note: NO prototype for get_str
int main()
{
    char *s = get_str();
    printf("String: %s\n", s);
    return 0;
}

Ну, компилятор должен помнить, что int и char* несовместимы (вскоре после того, как он предупреждает, что get_str предполагается возвращать int). Но что, если вы вынуждаете руку компилятора, сообщая ему, чтобы сделать char* так или иначе:

#include <stdio.h>

// Note: NO prototype for get_str
int main()
{
    char *s = (char*)get_str(); // NOTE: added cast
    printf("String: %s\n", s);
    return 0;
}    

Теперь, без предупреждения-as-errors, вы получите предупреждение о неявном объявлении, и вот оно. Код будет скомпилирован. Но будет ли он работать? Если sizeof(int)!= sizeof(char*), (32-разрядный и 64-разрядный), скорее всего, не будет. Значение, возвращаемое из get_str, - это 64-разрядный указатель, но вызывающий объект принимает только 32-битные данные, а затем приводит к 64-разрядному указателю. Короче говоря, приведение скрыло ошибку и открыло окно pandora из поведения undefined.


Итак, как все это относится к вашему коду? Не включая <stdlib.h>, компилятор не знает, что такое malloc. Поэтому он предполагает, что он имеет вид:

int malloc();

Затем, выведя результат в (int**), вы сообщаете компилятору, "что бы ни случилось, сделайте его int**". При времени ссылки _malloc найден (без сигнатуры параметра с помощью манипуляции с именем, например С++), подключен, и ваша программа готова к участию. Но на вашей платформе int и указатели данных не имеют одинакового размера, поэтому вы оказываете несколько нежелательных последствий:

  • Литой скрывается реальная ошибка.
  • Поддельный указатель производится из половины бит реального возвращенного указателя.
  • Как жестокая доза соли ране, выделенная память просачивается, так как нет действительных указателей где-нибудь, ссылающихся на нее (вы просто уничтожили единственную, оставив только половину ее).
  • Вероятно, наиболее нежелательно, код будет демонстрировать нормальное поведение, если он скомпилирован в реализации, где sizeof(int) == sizeof(int**).

Итак, вы создаете это на своем 32-битном поле Debian, все выглядит хорошо. Вы включаете свою домашнюю работу к профессору, который строит его на своем 64-битном Mac, и он падает, вы не выполняете задание, не сдаете класс, выходите из колледжа и проводите следующие десять лет, лаская кошку во время просмотра повторных попыток Seinfeld в подвале вашей мамы интересно, что пошло не так. Уч.

Не обрабатывайте отливку как серебряную пулю. Это не так. В C он нужен гораздо реже, чем люди его используют, и если он используется не в том месте, он может скрыть катастрофические ошибки. Если вы найдете точку в своем коде, где что-то не будет компилироваться без жесткого приведения, посмотрите еще раз. Если вы не абсолютно уверены в том, что актеры правильны, вероятность того, что это не так.

В этом случае он скрыл реальную ошибку, которую вы пренебрегли предоставлением компилятору достаточной информации, чтобы знать, что действительно делает malloc.

Ответ 2

Попробуйте следующее:

int **array;
array = malloc(rows * sizeof(int *));
for (i = 0; i < rows; i++)
  array[i] = malloc(cols * sizeof(int));

// Some testing
for (i = 0; i < rows; i++) {
  for (j = 0; j < cols; j++)
    array[i][j] = 0; // or whatever you want
}

for (i = 0; i < rows; i++) {
  for (j = 0; j < cols; j++)
    printf("%d ", array[i][j]);
}

В вашем случае строки = 160 и cols = 10. Это одно из возможных решений.

При таком подходе вы можете использовать два индекса:

Ответ 3

Чтобы выделить массив:

int *array = malloc(sizeof(int) * 160 * 10);

Затем используйте код типа:

array[10 * row + column] = value;

(Где row идет от 0 до 159 включительно, а column идет от 0 до 9 включительно.)

Ответ 4

У меня есть примечание для ответа rendon:

Для своего кода Visual С++ говорит для всех операций "=": error C2440: '=' : cannot convert from 'void *' to 'int **'

Сделав некоторые изменения, он работает для меня, но я не уверен, что он делает то же самое, поэтому я боюсь редактировать его код. Вместо этого вот мне код, который, кажется, работает для первого впечатления.

int **a;    

a = (int **)malloc(rows * sizeof(int));

for (i = 0; i < rows; i++)
{
    a[i] = (int *)malloc(cols * sizeof(int));
}

for (j=0;j<rows;j++)
{
    for (i=0;i<cols;i++)
    {
        a[i][j] = 2;
    }
}

Собственно, я сделал это с пользовательским struct вместо int, но я думаю, что в любом случае он должен работать.

Ответ 5

Не возражайте, я просто добавляю пример с помощью calloc

void allocate_fudging_array(int R, int C)
{
    int **fudging_array = (int **) calloc(R, sizeof(int *));
    for(int k = 0; k < R; k++)
    {
        fudging_array[k] = (int*) calloc(C, sizeof(int));
    }
}


// a helper function to print the array 
void print2darr(int **arr, int R, int C)
{
    for(int i = 0; i < R; i++)
    {
        for(int j = 0; j < C; j++)
        {
            printf(" %d  ", arr[i][j]);
        }
        printf("\n");
    }
}

Ответ 6

2D-массив для хранения char *

char ***array;
int rows = 2, cols = 2, i, j;
array = malloc(sizeof(char **)*rows);
for (i = 0; i < rows; i++)
  array[i] = malloc(cols * sizeof(char *));

array[0][0] = "asd";
array[0][1] = "qwe";
array[1][0] = "stack";
array[1][1] = "overflow";

for(i=0;i<rows;i++){
  for(j=0;j<cols;j++){
    printf("%s ",array[i][j]);
  }
  printf("\n");
}