J'implémente un tri générique en C selon une affectation. Dans cette affectation, j'ai besoin d'obtenir et de trier (en tri à bulles) un tableau de type void. La signature de la fonction est: void bubbleSort(void* arrayToSort,int lenArray,size_t sizeElements, int (*compare)(const void*,const void*)) J'ai un problème: je trouve que cette erreur "l'expression doit être un pointeur vers un type d'objet complet" presque dans tout ce que je fais. J'ai cherché, mais tous les conseils concernant cette erreur sont de la convertir d'abord dans le type réel. Je ne peux pas le lancer, car la fonction doit être générique et tout ce que je sais, c'est la taille du type du tableau. Est-ce que quelqu'un peut m'aider? Voici le code:

void bubbleSort(void* arrayToSort,int lenArray,size_t sizeElements, int (*compare)(const void*, const void*)) {
    bool didExcanged = false;
    for (int i = 0; i < lenArray && (!didExcanged); i++)
    {
        void* pivot = arrayToSort + i * sizeElements;//that error on "arrayToSort"
        didExcanged = false;
        for (int j = i; j < lenArray; j++)
        {
            void* toCompare = arrayToSort + j * sizeElements;//that error on "arrayToSort"
            if (compare(pivot,toCompare)>0) {
                swap(pivot, toCompare);
                didExcanged = true;
            }
        }
    }
}

Et la fonction swap:

void swap(void* a, void* b) {
    void *temp=*a;//that error on "*a"
    *a = *b;//that error on "*a" and "*b" 
    *b = *temp;//that error on "*b" and "*temp"
}
c
0
user14194901 31 août 2020 à 12:17

2 réponses

Meilleure réponse

void* est étrange en C. C'est techniquement un pointeur, mais il diffère également des autres types de pointeurs en ce qu'il ne peut pas être dé-référencé. Vous ne pouvez pas non plus faire d'arithmétique de pointeur dessus. Vous pouvez y stocker et récupérer n'importe quel type de pointeur, mais vous ne pouvez rien faire d'autre que le stocker ou le convertir en un autre type. Dans votre situation, la seule approche viable semble être celle qu'une implémentation memcpy utiliserait - transformez-la en un unsigned char * qui est garanti d'être dé-référençable pour n'importe quel type.

Exemple:

void my_memcpy(void* a, void* b, size_t size)
{
    unsigned char *p = (unsigned char*)a;
    unsigned char *q = (unsigned char*)b;
    while(size--)
    {
        *p++ = *q++;
    }
}

Un swap peut être implémenté en utilisant memcpy comme:

void swap(void* a, void* b, size_t size)
{
    unsigned char temp[size];
    memcpy(temp, a, size);
    memcpy(a, b, size);
    memcpy(b, temp, size);
}
0
th33lf 31 août 2020 à 09:49

Vous ne pouvez pas dé-référencer un void*, car le type void n'a pas de taille - c'est un type incomplet d'où l'avertissement "doit être un type d'objet complet ".

Vous ne pouvez pas écrire une fonction swap générique basée sur void* sans connaître la taille des objets de données, vous devez donc transmettre ces informations à swap.

1
Lundin 31 août 2020 à 09:38