Использование void * в C вместо перегрузки? - PullRequest
3 голосов
/ 09 декабря 2010

Мой вопрос здесь: я видел такой код для многопоточного приложения:

void Thread( void* pParams )
{  
    int *milliseconds = (int *)pParams;
    Sleep(milliseconds);
    printf("Finished after %d milliseconds", milliseconds); //or something like that
}

Это очень заинтересовало меня, я знал, что malloc отправляет обратно указатель void, и вы можете привести его к тому, что вы хотите, означает ли это, что я могу создать функцию, которая может принимать любой тип данных?

Например, функция, которую я написал без тестирования:

void myfunc( void* param )
{  
    switch(sizeof(param)) {
       case 1:
       char *foo = (char *)param; break;
       case 2:
       short *foo = (short *)param; break;
       case 4: 
       int *foo = (int *)param; break;
    }
}
myfunc(3.1415);
myfunc(0);
myfunc('a');

Я могу быть совершенно неправ, даже если это работает, это ужасная практика? Благодаря.

Ответы [ 5 ]

7 голосов
/ 09 декабря 2010

Да, можно создать функцию, которая принимает несколько типов, но это не то, как вы это делаете.

В вашем myfunc, sizeof(param) всегда будет одинаковым: sizeofопределяется во время компиляции и будет иметь размер указателя.

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

Ключ с void *: вы можете привести их обратно к тому, что было впервое место, и это зависит от вас, чтобы знать, что это такое.Простой void * сам по себе не может сказать вам, на что он указывает.

7 голосов
/ 09 декабря 2010

да, void * отлично подходит для создания универсальных функций.Однако, как только вы передадите указатель на определенный тип данных в функцию, которая принимает void *, вы потеряете всю информацию о типе.Один из способов управлять вашей программой, чтобы она знала, какой тип вы передали, - это иметь второй параметр типа enum, который может иметь такие значения, как INT, FLOAT, DOUBLE и т. Д. И т. Д.

#include <stdio.h>

typedef enum inputTypes
{
    INT,
    DOUBLE,
    CHAR
} inType;

void myfunc(void*, inType);

int main(void)
{
    int    i = 42;
    double d = 3.14;
    char   c = 'a';

    myfunc(&i, INT);
    myfunc(&d, DOUBLE);
    myfunc(&c, CHAR);

    return 0;
}

void myfunc(void* param, inType type)
{  
    switch(type) {
       case INT:
           printf("you passed in int %d\n", *((int *)param));
           break;
       case DOUBLE:
           printf("you passed in double %lf\n", *((double *)param));
           break; 
       case CHAR: 
           printf("you passed in char %c\n", *((char *)param));
           break;
    }
}

Выход

you passed in int 42
you passed in double 3.140000
you passed in char a
0 голосов
/ 09 декабря 2010

Не работает, потому что sizeof(param) пытается получить размер указателя.

0 голосов
/ 09 декабря 2010

Размер void* полностью зависит от системы и определяется во время компиляции, а не от того, что фактически содержится в нем.

0 голосов
/ 09 декабря 2010

sizeof(param) всегда будет возвращать размер указателя, поэтому предположительно 8, если вы работаете в 64-битной системе. Это не имеет ничего общего с тем, на что оно указывает.

...