能否访问并向void**写入数据?如何存储未知类型数据?
问题分析与解决方案
为什么会出现段错误?
你的代码存在两个核心问题:
- 类型不匹配:你把
malloc返回的void*直接赋值给void** d。void**是「指向void指针的指针」,而你malloc的是一块用来存储int的内存,并非存储void*的数组,类型完全不兼容。 - 访问非法地址:
malloc分配的内存未初始化,*d会读取这块内存前sizeof(void*)字节的随机值当作地址,你把这个随机地址强转为int*后解引用,必然会访问非法内存,触发段错误。
至于第一个例子中sizeof(*( (int *) *d ))能输出4,是因为sizeof是编译期计算的操作——编译器只需要知道*(int*)x的类型是int,直接返回int的大小,不会实际访问*d指向的内存,所以不会出错。
如何正确访问这块内存?
如果要存储int类型数据,直接用对应类型的指针接收malloc返回值即可:
int *d = malloc(sizeof(int) * 10); *d = 1; // 直接给第一个int元素赋值,完全合法
如果确实需要用通用的void*存储,应该用void*而非void**:
void *d = malloc(sizeof(int) * 10); *(int*)d = 1; // 将void*强转为int*后解引用赋值,正确
void**的适用场景是存储多个void指针的集合(比如不同类型对象的指针数组),不是用来存储普通数值类型的。
如何存储类型未知的数据?
通常有两种常用方案:
1. 标签联合(Tagged Union)
定义一个包含类型标记和联合的结构体,用标记区分当前存储的数据类型,联合用来容纳不同类型的数据:
// 定义类型标记枚举 typedef enum { TYPE_INT, TYPE_FLOAT, TYPE_STRING } DataType; // 通用数据结构体 typedef struct { DataType type; union { int i_val; float f_val; char* s_val; } data; } GenericData; // 使用示例 GenericData data_list[10]; // 存储int data_list[0].type = TYPE_INT; data_list[0].data.i_val = 42; // 存储float data_list[1].type = TYPE_FLOAT; data_list[1].data.f_val = 3.14f; // 读取时根据类型判断 if (data_list[0].type == TYPE_INT) { printf("Int value: %d\n", data_list[0].data.i_val); }
2. void*数组+类型信息数组
如果需要存储不同类型的指针(而非值本身),可以用void*数组存储指针,同时用额外数组记录每个元素的类型:
void* ptr_arr[10]; DataType type_arr[10]; // 存储int变量的指针 int num = 100; ptr_arr[0] = # type_arr[0] = TYPE_INT; // 存储字符串指针 char* str = "hello"; ptr_arr[1] = str; type_arr[1] = TYPE_STRING; // 读取示例 if (type_arr[0] == TYPE_INT) { printf("Int value: %d\n", *(int*)ptr_arr[0]); }
注意:如果存储的是需要动态分配内存的数据(比如字符串),需要自行管理内存的分配与释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Ilya
相关产品推荐
相关产品推荐

