【问题标题】:Using a function with a void pointer argument使用带有 void 指针参数的函数
【发布时间】:2016-07-04 02:44:20
【问题描述】:

我是一名 C 初学者,正在尝试使用链表,我找到了一个 Github 存储库。 create 函数是这样写的:

Node* ListCreate(void* data) {
    Node *head = malloc(sizeof(Node));
    if ( head != NULL) {
        head->next = NULL;
        head->data = data;
    }
    return head;
}

我可以通过将void* 更改为int 然后在main 中执行以下操作来使用它:

Node *root = ListCreate(5);

但后来我读了一些关于 void 指针的内容,似乎它们可以用作类似于 C++ 模板的泛型类型,如果我能弄清楚它们是如何工作的,这将很有用。我尝试了几件事,最接近它的工作是没有错误,但有一个警告:

incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'

我在这里错过了一步吗?我首先觉得我应该在函数定义中添加一些东西,但我假设编写它的人知道他们在做什么,而我只是在main 中没有正确使用它。那么我应该以不同的方式将参数传递给这个函数吗?

【问题讨论】:

  • 当单个函数要处理不同类型的数据时(尤其是当传递指向这些不同类型数据的指针有意义时),但当它处理单个函数时,您可能会使用 void 指针类型,你通常会尽量避免这种情况。请注意,像 qsort()bsearch() 这样的函数会传递 void 指针——因此,如果您使用它们,您将拥有接受 void 指针但将传递的指针转换为正确(预期)类型的函数。如果没有显式强制转换,就不能从整数类型转换为指针;你根本无法从浮点类型转换。
  • 我试图让我的链表数据可以设置为整数、浮点数或字符。这在 C 中比在 C++ 中更难做到吗?
  • 好的;列表中的数据类型是什么?您是存储int 值还是int * 值?处理int * 在列表代码中很容易,但在使用列表代码的代码中更难——您必须为每个指向的指针有一个单独的int 变量,以便您可以将它们存储在列表中(并且有空间浪费,因为你有指针和它指向的值)。 float 同上。当您说char 时,您是指单个字符(硬)还是字符串(又名char *,相对容易)?
  • 有多种方法可以强制执行同质性,但一种是为不同的成员类型设置不同的列表类型。您只需在下面以void * 的形式实现它们。您需要考虑的一个问题是“哪些操作适用于您的列表”。创建列表,将项目添加到列表,从列表中删除项目,销毁列表 - 它们很容易,而且几乎没有争议(尽管您需要考虑谁管理数据内存以避免泄漏)。如果你想在列表中查找值,或者打印列表,或者对列表中的每个项目应用一个函数,你必须更加努力。
  • 在跑步之前通常更容易走路。 :D

标签: c void-pointers


【解决方案1】:

正如其他人在评论中提到的,为不同的类型创建不同的列表更合适。

但是如果你想使用相同的函数定义,那么 use 可以将指针传递给你的数据(intchar)并将它们转换为void *

/* main: start */
int main(void)
{
    Node *list_head;  /* Points to first element in list */
    Node *node_tmp;   /* Just a temporary pointer */

    int   *pint;
    char  *pchar;

    /* create an empty list */
    list_head = NULL;

    /* Note that there is no error checking done for
     * malloc, which is not good
     */

    /* Create a node which points to int */
    pint = malloc(sizeof(int));
    *pint = 10; 
    node_tmp = ListCreate((void *) pint);
    /* Add this node to list */
    list_head = add(node_tmp, list_head);

    /* Create a node which points to char */
    pchar = malloc(sizeof(char));
    *pchar = 'c';
    node_tmp = ListCreate((void *) pchar);
    /* Add this node to list */
    list_head = add(node_tmp, list_head);

    /* print total number of nodes in list */
    print_tot_nodes(list_head);
    return 0;
}

为简洁起见,省略了 addprint_tot_nodes 的代码。

请注意,如果data 指向不同的数据类型,则print_tot_nodesadd 之类的函数不会有太大问题。但是如果你需要实现像Node *smallest(Node *head)这样的函数,它返回指向具有最小元素的节点的指针,那么它可能会变得复杂。

因此,为不同的类型使用不同的列表更容易。但是,如果您需要使用与原始帖子中相同的函数定义,则可以cast 将指向某些数据类型的实际指针指向void *

【讨论】:

    【解决方案2】:

    我认为需要对数字文字(或强制转换?)进行换行。
    像这样:

    void *BOX_VAR;//Not require if use GCC extension
    #define BOX(type, value) ((*(type *)(BOX_VAR=malloc(sizeof(type))) = value), BOX_VAR)
    #define UNBOX(type, value) (*(type *)(value))
    
    Node *list = ListCreate(BOX(int, 5));
    int v = UNBOX(int, list->data);
    printf("%d\n", v);
    

    【讨论】:

      猜你喜欢
      • 2021-05-09
      • 2018-08-25
      • 2014-09-05
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      • 2020-06-11
      相关资源
      最近更新 更多