Массив указателей - распределение памяти - PullRequest
0 голосов
/ 01 июня 2019

Я новичок в массиве указателей (помещаю функции в массив) и выделяю для него память с помощью malloc.Можете ли вы помочь мне с этим фрагментом кода?Имеют функции: int comp_int(int a, int b); int comp_int_abs(int a, int b); int comp_int_length(int a, int b); int comp_int_digits_sum(int a, int b); и хотели бы поместить указатели на эти функции в массив указателей.Во-первых, хотелось бы динамически распределять память для массива и помещать в него указатели функций.Застрял в этом месте, что я делаю не так?

int (**funcs)(int, int) = malloc(4*sizeof(int));

if(!*funcs)
{
    printf("Failed to allocate memory");
    return 8;
}

*funcs={add_int, sub_int, div_int, mul_int};

Ответы [ 2 ]

4 голосов
/ 01 июня 2019

Прежде всего, зачем выделять динамическую память?

Если вы используете обычный массив, все становится немного проще:

int (*funcs[])(int, int) = {
    comp_int,
    comp_int_abs,
    comp_int_length,
    comp_int_digits_sum,
};

Если вы хотите использовать динамическое размещение, есть несколько вещей, на которые стоит обратить внимание.

int (**funcs)(int, int) = malloc(4 * sizeof *funcs);

Сначала нам нужно выделить правильное количество памяти. Умножая на размер разыменованного указателя, нам не нужно беспокоиться о типе элемента динамического массива. (Но если бы мы хотели написать тип вручную, это было бы sizeof (int (*)(int, int)), а не sizeof (int), как в вашем коде; элементы нашего массива являются указателями на функции, а не целыми числами.)

Затем мы проверяем наличие ошибки выделения:

if (!funcs) {

Примечание. Мы проверяем сам указатель (funcs), а не первый элемент динамического массива (который может не существовать!), Как в вашем коде (*funcs). Если malloc завершится ошибкой и вернет NULL, !*funcs попытается разыменовать нулевой указатель, что, скорее всего, приведет к аварийному завершению вашей программы.

    fprintf(stderr, "Failed to allocate memory\n");

Сообщения об ошибках идут на stderr, а не stdout. Строки заканчиваются на '\n'.

    return 8;
}

Поскольку у нас нет реального массива, мы не можем использовать синтаксис инициализации. В частности, = { недопустимо в выражениях присваивания.

Самое простое решение - назначить элементы вручную:

funcs[0] = comp_int;
funcs[1] = comp_int_abs;
funcs[2] = comp_int_length;
funcs[3] = comp_int_digits_sum;

Это немного подвержено ошибкам, потому что мы должны указывать каждый индекс вручную. Однако мы можем объединить это с кодом «нормального массива» сверху:

int (*const funcs_init[])(int, int) = {
    comp_int,
    comp_int_abs,
    comp_int_length,
    comp_int_digits_sum,
};

int (**funcs)(int, int) = malloc(sizeof funcs_init);
if (!funcs) { ... }

memcpy(funcs, funcs_init, sizeof funcs_init);

Мы просто инициализируем наш массив как обычно (здесь он называется funcs_init), затем копируем содержимое в нашу динамически выделенную память, используя memcpy.

1 голос
/ 01 июня 2019

Сначала измените распределение с:

int (**funcs)(int, int)=malloc(4*sizeof(int));

на

int (**funcs)(int, int)=malloc(4*sizeof(*funcs));

Измените

*funcs={add_int, sub_int, div_int, mul_int};

на

funcs[0]=add_int;
funcs[1]=sub_int;
funcs[2]=div_int;
funcs[3]=mul_int;

нотация с фигурными скобками, {} может использоваться только при инициализации, но не при присвоении.Если вы используете массив вместо указателя, вы можете сделать это:

int (*funcs[4])(int, int)={add_int, sub_int, div_int, mul_int};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...