Как пройти через параметр массива как указатель void

У меня есть похожая "общая" процедура, такая как qsort, которая имеет пустой указатель (указывающий на массив), а также параметр указателя функции. Эта функция должна работать с любым типом массива.

Пример:

void do_something(void * array, int count, int size, void (*test)(const void*)){
    int i;
    for(i=0; i<count; i++){
        test(array + (index * size));
    }
}

Это, однако, дает мне следующее предупреждение (gcc test.c -pedantic-errors):

error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]

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

Так как же стандартная библиотека делает такие вещи для qsort? Глядя на этот код: ( http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c) я вижу следующее:

void
_quicksort (void *const pbase, size_t total_elems, size_t size,
        __compar_fn_t cmp)
{
  register char *base_ptr = (char *) pbase;
  ....
  char *lo = base_ptr;
  char *hi = &lo[size * (total_elems - 1)];
  ...
}

Они приводят к (char *) независимо от фактического типа?

3 ответа

Решение

Я задал похожий вопрос Могу ли я сделать арифметику на указатели void * в C?,

Арифметика Void * не определена. Что значит добавить 1 к пустому указателю? Большинство компиляторов (если они позволяют это) обрабатывают это как увеличение на sizeof(char) ("следующий байт"), но предупреждают вас.

Так что правильно сделать, это явно заставить его делать то, что вы хотите -> привести к char* и увеличить это

Арифметика указателей на неполный тип данных void это не законно, и именно на это жалуется компилятор.

Как вы можете видеть в _quicksort() указатель является константой, поэтому вы не можете изменить адрес, на который указывает указатель. Там нет артемической операции, происходящей на void указатель.

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

По этой причине компиляторы не выполняют арифметику с пустыми указателями. Чтобы выполнить арифметику указателей, компилятору необходимо знать тип указателя, чтобы он мог выполнять правильные преобразования (если указатель содержит целое число, он не будет добавлять 32-битные значения или, по крайней мере, позволит знаю, что что-то пошло не так!).

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

Другие вопросы по тегам