Пустые указатели в C++

Я записал этот qsort:

void qsort(void *a[],int low,int high, int (*compare)(void*,void*));

Когда я обращаюсь к этому

char *strarr[5];

Это говорит что недопустимое преобразование из символа ** для освобождения **. Почему это неправильно?

Это - код:

#include<cstdlib>
#include<cstdio>
#include<iostream>

using namespace std;

inline void strswap(void *a,void *b) {
    char *t=*(char**)a;
    *(char**)a=*(char**)b;
    *(char**)b=t;
}

int strcompare(void *a, void *b) {
    return strcmp(*(char**)a,*(char**)b);
}

void qsort1(void *a[],int low,int high, int (*compare)(void*,void*), void (*swap)(void*,void*)) {
    if(low>=high)
        return;
    int q=low-1;
    for(int i=low;i<=high-1;i++)
        if((*compare)(&a[i],&a[high]) < 0)
            swap(&a[i],&a[++q]);
    swap(&a[high],&a[++q]);
    qsort1(a,low,q-1,compare,swap);
    qsort1(a,q+1,high,compare,swap);
}

int main() {
    const  int n=3;
    //int a[n]={4,6,8,12,10,9,8,0,24,3};
    char *strarr[5]={"abcd","zvb","cax"};
    qsort1(strarr,0,n-1,strcompare,strswap);
    for(int i=0;i<n;i++)
        cout << strarr[i] << " ";
    cout << endl;
    return 0;
}
5
задан Anders Abel 7 August 2011 в 20:08
поделиться

2 ответа

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

Это не означает, что void * имеет тот же размер или представление, что и любой другой тип указателя: преобразование указателя из другого типа указателя в void * не обязательно оставить базовое представление неизменным .Преобразование из double * в void * аналогично преобразованию из double в int - это должно происходить на виду у компилятора , вы не можете скрыть это преобразование за спиной компилятора.

Таким образом, это означает, что хотя void * является универсальным указателем, void ** является не универсальным указателем на указатель. Это указатель на void * - указатель void ** должен указывать только на реальные объекты void * (тогда как void * сам может указывать на что угодно).

Вот почему нет неявных преобразований между типом ** и void ** - по той же причине, по которой нет неявных преобразований между double * и int * .

Теперь есть один особый случай: по историческим причинам char * гарантированно будет иметь тот же размер, представление и требования к выравниванию, что и void * . Это означает, что преобразования между char ** (в частности) и void ** на самом деле допустимы, как исключение из общего правила. Таким образом, в вашем конкретном случае ваш код верен, если вы добавляете приведение к void ** , когда вы передаете strarr в qsort1 () ].

Однако ваш qsort1 () определен только для правильной работы с массивами void * или char * (включая unsigned char * и др.).Вы не можете использовать его, например, для сортировки массива указателей double * (хотя сегодня он действительно работает в большинстве распространенных сред).

12
ответ дан 18 December 2019 в 07:08
поделиться

Любой указатель может быть неявно преобразован в указатель void. Но ваш первый параметр не является указателем void - это массив указателей void, и неявного преобразования для него не существует. Возможно, вы хотите объявить свою функцию как:

void qsort(void *,int low,int high, int (*compare)(void*,void*));

но трудно сказать, не видя кода.

10
ответ дан 18 December 2019 в 07:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: