为什么传递 void 指针而不是自定义类型?

问题描述 投票:0回答:1

我正在从另一个人那里接管代码。我发现了一种对我来说似乎很奇怪的编码模式。这是针对嵌入式 32 位 PIC 处理器(如果相关的话)。

它们在头文件中有一个自定义 typedef,类似于以下内容:

typedef struct {
     custom_object obj;
     char** list;
     uint8_t length;
     //other variables here
} custom_list;

但是每当将此 custom_list 类型传递给函数时,都会像这样调用:

void custom_function(void* obj) {
    custom_list *list = (custom_list*) obj;

    //miscellaneous code here... 
}

他们将变量作为指向 void 的指针传递,然后将其重新转换为指向函数内的 custom_list 的指针。

为什么不像这样直接将类型指针传递给 custom_list 呢?

void custom_function(custom_list* list) {

    //miscellaneous code here... 
}

将其作为指向 void 的指针传递然后重新转换它不是额外的步骤吗?这不是一个坏习惯吗……他们这样做只是为了解决编译器检查器错误吗?或者我错过了什么,第一种方法有什么优势或必要吗?

c pass-by-reference void-pointers
1个回答
0
投票

造成这种情况的原因可能有多种。例如,该函数可以用作某个地方另一个更通用函数的参数。

这里是一个简单的例子,不完全是实用的C代码,但是很容易理解。这是映射函数的简单实现,将给定的函数应用于数组中的每个元素。

#include <stdio.h>
#include <ctype.h>

void map(int len, void** array, void (*operator)(void*)) {
    for (int i = 0; i < len; i++)
        operator(array[i]);
}

void caesar_encode(void* val) {
    char* str = val;
    for (int i = 0; str[i]; i++) {
        if (!isalpha(str[i]))
            continue;
        char offset = islower(str[i]) ? 'a' : 'A';
        str[i] = (str[i] - offset + 4) % 26 + offset;
    }
}

void main(int argc, char** argv) {
    map(argc - 1, (void**) argv + 1, caesar_encode);
    for (int i = 1; i < argc; i++)
        printf("%s ", argv[i]);
    printf("\n");
}

该程序将凯撒编码应用于传递给该程序的参数中的每个字母字符。

类似的一个实际示例是pthread_create,用于创建新的线程对象。

pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg)

线程启动的函数必须具有签名

void *(*start_routine)(void *)
,允许您传递任何您喜欢的数据(例如打包在结构中)。


另一个原因可能是编写代码的人不喜欢不透明的指针类型。标题可能看起来像这样:

...
typedef struct custom_list* CustomList;
CustomList create_custom_list();
void destroy_custom_list(CustomList);
...

因此,也许编写代码的人只是不喜欢不透明的指针类型并且不习惯它们,或者代码来自它们出现之前的时代。我现在只是猜测。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.