C 使用带有空指针参数的函数

C 使用带有空指针参数的函数,c,void-pointers,C,Void Pointers,我是一个C初学者,正在试验链表,我发现了一个Github repo。create函数的编写方式如下: Node* ListCreate(void* data) { Node *head = malloc(sizeof(Node)); if ( head != NULL) { head->next = NULL; head->data = data; } return head; } 我可以通过将void*更改为int然

我是一个C初学者,正在试验链表,我发现了一个Github repo。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);

但是我读了一些关于空指针的文章,它们看起来可以像C++模板一样使用泛型类型,如果我能弄清楚它们是如何工作的话,这将是很有用的。我尝试了几种方法,最接近于让它工作的方法是没有错误,但有一个警告:

将'int'传递给'void*'类型的参数的整数到指针转换不兼容。


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

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

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

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

但是,如果要使用相同的函数定义,那么use可以将指针传递给数据(
int
char
),并将它们转换为
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;
}
添加和打印节点的代码是为了简洁

请注意,如果
数据
指向不同的数据类型,则像
打印到节点
添加
这样的函数不会有太多问题。但是如果您需要实现像
Node*minimest(Node*head)
这样的函数,该函数返回指向具有最小元素的节点的指针,那么它可能会变得复杂


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

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