Как разбить общий массив void на части.c

как новичок в C, я борюсь с неясной проблемой, и, поскольку я не мог найти решение этой конкретной проблемы, я хочу спросить вас о следующем: в настоящее время я пытаюсь понять указатели void и их арифметические операции. Я попытался написать общую функцию, которая принимает пустой указатель на массив, длину массива и размер одного элемента и разбивает данный массив на две разные части (список1 и список2):

void split(void *array, int arrlen, int objsize)
{
// divide the arrlen and save the values
    int len_list1 = arrlen / 2;
    int len_list2 = arrlen - len_list1;

// Allocate memory for two temporary lists
    void *list1 = (void*)malloc(objsize * len_list1);
    void *list2 = (void*)malloc(objsize * len_list2);

    if (list1 == NULL || list2 == NULL)
    {
        printf("[ERROR]!\n");
        exit(-1);
    }

// list1 gets initialized properly with int and char elements
    memmove(list1, array, len_list1*objsize);           
    printf("list1:"); 
    print_arr(list1, len_list1);

// memmove((char*)list2, (char*)array+list_1_length, list
memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize);
//memmove((int*)list2, (char*)array+list_1_length, list_2_length*objsize);
length*objsize); (*) memmove(list2, (int*)array+len_list1, len_list2*objsize); printf("list2:"); print_arr(list2, len_list2); }

Моя проблема заключается в следующем: если я передам этой функции массив int, она будет работать нормально, но если я вызову функцию split() с массивом символов в качестве аргумента, мне придется...

memmove((char*)list2, (char*)array+list_1_length, list_2_length*objsize);
//memmove((int*)list2, (char*)array+list_1_length, list_2_length*objsize);

строку комментария (*), чтобы получить те же результаты. Решение, безусловно, может состоять в том, чтобы написать условие if-else и проверить objsize:

if (objsize == sizeof(int))
    // move memory as in the 1st code snippet
else
    // move memory with the (int*) cast

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

Спасибо!

-мацуи


person matzui    schedule 24.01.2015    source источник
comment
В качестве дополнительной информации для читателей, в вашем фрагменте есть еще несколько серьезных недостатков. Во-первых, в C нет никакой сборки мусора, поэтому вы должны использовать free для list1 и list2 после того, как закончите с ними. Кроме того, memmove может пригодиться, но поскольку вы копируете данные в блоки памяти, которые только что были выделены, у вас есть гарантия, что array, list1 и list2 не будут перекрываться, поэтому вы должны использовать здесь memcpy (из string.h). Пожалуйста, рассмотрите мое редактирование вашего поста.   -  person dummydev    schedule 29.05.2015


Ответы (2)


memmove(list2, (int*)array+len_list1, len_list2*objsize);

Здесь вы приводите тип array к int * и добавляете к нему len_list1. Но добавление чего-либо к указателю означает, что он будет умножен на размер одного элемента типа данных этого указателя. Таким образом, если int имеет размер 4 байта, и вы добавляете 5 к переменной int *, она переместится на 20 байт.

Поскольку вы точно знаете, на сколько байтов вы хотите переместить указатель, вы можете привести его к char * (char = 1 байт) и добавить к нему количество байтов.

Так что вместо (int*)array+len_list1 можно использовать (char*)array+(len_list1*objsize)

person wimh    schedule 24.01.2015

Пустой указатель — это всего лишь разыменованный указатель размером с слово, который не подразумевает никакого конкретного типа данных. Таким образом, вы не можете выполнять с ним математические операции с указателями. Чтобы сделать то, что вы пытаетесь сделать, объявите указатель соответствующего типа в своей функции, а затем установите его значение равным значению указателя параметра void.

person Curt    schedule 24.01.2015
comment
Что вы имеете в виду под правильно типизированным указателем? Думали ли вы о чем-то вроде void tmp = (char)array + i*objsize для доступа к i-му элементу? - person matzui; 25.01.2015