【问题标题】:Using void * in C in place of overloading?在 C 中使用 void * 代替重载?
【发布时间】:2011-05-22 12:04:48
【问题描述】:

我的问题是,我曾在多线程应用程序中看到过这样的代码:

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');

我可能完全错了,即使这确实有效,这是一种可怕的做法吗?谢谢。

【问题讨论】:

    标签: c function void-pointers


    【解决方案1】:

    是的,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
    

    【讨论】:

    • 啊!我试图理解你的意思,但这个例子真的很有意义!谢谢你写它! :) 我会尝试从头开始编写并尝试了解更多信息。
    • 这让我想起了可变参数,就像在 printf() 中一样,第一个参数表示其他参数是什么。
    【解决方案2】:

    是的,可以创建一个接受多种类型的函数,但你不是这样做的。

    在您的myfunc 中,sizeof(param) 将始终相同:sizeof 在编译时确定,并且将是指针的大小。

    它适用于线程的原因是,编码器通常在编译时就知道指针指向的内容,而您只需要一个简单的转换即可。如果您在编译时不知道 void * 指向什么,则必须在运行时以某种方式传递它。

    void * 的关键:您只能将它们恢复到最初的状态,而这取决于您知道那是什么。一个简单的void * 本身无法告诉您它所指向的内容。

    【讨论】:

    • 啊,这完全有道理。我看到做我在想的事情有一些用处,但在很多情况下都没有。我想我会把它放在我无用的 C 技巧包中——我至少对指针了解更多!
    【解决方案3】:

    sizeof(param) 将始终返回指针的大小,因此如果您在 64 位系统上,大概是 8。这与它指向的内容无关。

    【讨论】:

      【解决方案4】:

      不起作用,因为sizeof(param) 正在尝试获取指针的大小。

      【讨论】:

        【解决方案5】:

        void* 的大小完全取决于系统并在编译时确定,而不是取决于其中实际包含的内容。

        【讨论】:

          猜你喜欢
          • 2012-03-18
          • 2011-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-06
          • 2019-06-21
          • 2023-04-08
          • 1970-01-01
          相关资源
          最近更新 更多