gpt4 book ai didi

c - 在 C 中存储和使用类型信息

转载 作者:太空宇宙 更新时间:2023-11-04 03:22:03 24 4
gpt4 key购买 nike

我来自 Java,我正在尝试在 C 中实现双向链表作为练习。我想做一些类似于 Java 泛型的事情,我将一个指针类型传递给列表初始化,这个指针类型将用于转换列表 void 指针,但我不确定这是否可能?

我正在寻找的是可以存储在列表结构中并用于将 *data 从节点转换为正确类型的东西。我正在考虑使用双指针,但后来我需要将其声明为空指针,我会遇到同样的问题。

typedef struct node {
void *data;
struct node *next;
struct node *previous;
} node;

typedef struct list {
node *head;
node *tail;
//??? is there any way to store the data type of *data?
} list;

最佳答案

通常,使用如下所示的特定函数。

void    List_Put_int(list *L, int *i);
void List_Put_double(list *L, double *d);
int * List_Get_int(list *L);
double *List_Get_double(list *L);

对于初学者来说不太容易的方法是使用_Generic。 C11 提供 _Generic,它允许在编译时根据类型根据需要控制代码。

下面提供了保存/获取 3 种类型指针的基本代码。宏需要为每个新类型扩展。 _Generic 不允许列出可能相同的 2 种类型,例如 unsigned *size_t *。所以有局限性。

type_id(X) 宏为 3 种类型创建枚举,可用于检查运行时问题,如 LIST_POP(L, &d);下面。

typedef struct node {
void *data;
int type;
} node;

typedef struct list {
node *head;
node *tail;
} list;

node node_var;
void List_Push(list *l, void *p, int type) {
// tbd code - simplistic use of global for illustration only
node_var.data = p;
node_var.type = type;
}

void *List_Pop(list *l, int type) {
// tbd code
assert(node_var.type == type);
return node_var.data;
}

#define cast(X,ptr) _Generic((X), \
double *: (double *) (ptr), \
unsigned *: (unsigned *) (ptr), \
int *: (int *) (ptr) \
)

#define type_id(X) _Generic((X), \
double *: 1, \
unsigned *: 2, \
int *: 3 \
)

#define LIST_PUSH(L, data) { List_Push((L),(data), type_id(data)); }
#define LIST_POP(L, dataptr) (*(dataptr)=cast(*dataptr, List_Pop((L), type_id(*dataptr))) )

使用示例和输出

int main() {
list *L = 0; // tbd initialization
int i = 42;
printf("%p %d\n", (void*) &i, i);
LIST_PUSH(L, &i);
int *j;
LIST_POP(L, &j);
printf("%p %d\n", (void*) j, *j);
double *d;
LIST_POP(L, &d);
}

42
42
assertion error

关于c - 在 C 中存储和使用类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44684292/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com