使用void*指针打包多类型数据后,能否正确解析访问其中内容?
问题分析与解决方案
核心问题:你的代码未实现连续内存打包
你当前的代码完全没有把数据写入到同一块连续内存中,pack只是被反复赋值为各个变量的独立地址,之后的指针偏移也没有实际存储数据。所以你设想的[char, char, size_t, size_t, size_t, char, char, char]连续内存布局根本不存在。
举个例子,这段循环:
for(int i = 0; i < size; i++, pack++, str++ ){ pack = str; }
每次循环pack都会被重新赋值为str的当前地址,pack++的偏移操作完全无效,没有任何数据被写入到内存中。后续对size、size2、zero的操作也是同理,只是让pack指向这些变量的栈地址,没有把它们的值拷贝到连续内存块里。
正确的打包实现(符合void*要求)
要实现你想要的连续内存布局,第一步需要分配一块足够大的连续内存,然后通过memcpy把数据依次写入:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *str = "hi"; char *str2 = "bye"; size_t size = 2; size_t size2 = 3; size_t zero = 0; // 计算总内存需求:2个char + 3个size_t + 3个char size_t total_size = sizeof(char)*2 + sizeof(size_t)*3 + sizeof(char)*3; // 分配连续内存,用void*接收 void *pack = malloc(total_size); if (!pack) { perror("malloc failed"); return 1; } void *current = pack; // 用current跟踪当前写入位置 // 写入第一个字符串的2个char memcpy(current, str, sizeof(char)*2); current = (char*)current + sizeof(char)*2; // 按字节偏移,更规范 // 写入三个size_t变量 memcpy(current, &size, sizeof(size_t)); current = (char*)current + sizeof(size_t); memcpy(current, &size2, sizeof(size_t)); current = (char*)current + sizeof(size_t); memcpy(current, &zero, sizeof(size_t)); current = (char*)current + sizeof(size_t); // 写入第二个字符串的3个char memcpy(current, str2, sizeof(char)*3); current = (char*)current + sizeof(char)*3; // 解包演示 printf("=== 解包结果 ===\n"); current = pack; // 读取前2个char char c1 = *(char*)current; current = (char*)current + sizeof(char); char c2 = *(char*)current; current = (char*)current + sizeof(char); printf("前两个字符:%c, %c\n", c1, c2); // 读取3个size_t size_t s1 = *(size_t*)current; current = (char*)current + sizeof(size_t); size_t s2 = *(size_t*)current; current = (char*)current + sizeof(size_t); size_t s0 = *(size_t*)current; current = (char*)current + sizeof(size_t); printf("三个size_t值:%zu, %zu, %zu\n", s1, s2, s0); // 读取后3个char char c3 = *(char*)current; current = (char*)current + sizeof(char); char c4 = *(char*)current; current = (char*)current + sizeof(char); char c5 = *(char*)current; current = (char*)current + sizeof(char); printf("后三个字符:%c, %c, %c\n", c3, c4, c5); free(pack); // 释放内存 return 0; }
void*遍历与访问的关键注意事项
void*不能直接解引用(比如*pack是非法的),必须先强制转换为对应类型的指针(如(char*)pack或(size_t*)pack)才能读取数据。- 指针偏移时,推荐先转换为
char*再操作,因为char的大小固定为1字节,偏移逻辑更清晰,避免编译器对void*算术运算的差异处理。 - 解包必须严格遵循打包的顺序和数据类型,否则会出现内存对齐错误或数据解析混乱。
为什么你之前的遍历找不到size_t变量
因为你从未把size、size2、zero的值写入到连续内存中,这些变量本身存储在栈上的分散位置,pack只是在指向它们的独立地址,并非连续内存块,所以遍历自然无法按预期找到这些值。
内容的提问来源于stack exchange,提问作者Zo3
相关产品推荐
相关产品推荐

