news 2026/10/17 5:36:41

【c++随笔29】结构体和char*转换(序列化和反序列化)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【c++随笔29】结构体和char*转换(序列化和反序列化)

【c++随笔29】结构体和char*转换(序列化和反序列化)

  • 1. 将结构体转换为 char*(序列化)
  • 2. 将 char* 转换为结构体(反序列化)
  • 3. 使用 std::string 替代 char*
  • 4、结构体转换为char*的其他写法

原创作者:郑同学的笔记
原文链接:https://zhengjunxue.blog.csdn.net/article/details/144650056

在 C++ 中,结构体(struct)和 char* 之间的转换通常涉及将结构体的内容序列化为一个字节流(即 char* 指针指向的内存块),或者将 char* 字节流解析回结构体。以下是两种常见的情况和解决方案:

1. 将结构体转换为 char*(序列化)

这通常是将结构体的内存内容以字节流的形式存储,便于网络传输或文件保存。

示例代码

#include<iostream>#include<cstring>// 用于 memcpy// 定义一个结构体structMyStruct{intid;floatvalue;charname[50];};intmain(){// 创建一个结构体实例MyStruct myStruct={123,45.67f,"Example"};// 将结构体内容复制到一个 char* 数组(字节流)char*buffer=newchar[sizeof(MyStruct)];std::memcpy(buffer,&myStruct,sizeof(MyStruct));// 输出字节流的内容std::cout<<"Serialized buffer content: ";for(size_t i=0;i<sizeof(MyStruct);++i){std::cout<<static_cast<int>(buffer[i])<<" ";}std::cout<<std::endl;// 释放内存delete[]buffer;return0;}
  • 解释:
    使用 memcpy 函数将结构体的内存内容复制到一个 char* 缓冲区中。
    sizeof(MyStruct) 用来获取结构体的大小,以确保拷贝足够的字节。
    new char[sizeof(MyStruct)] 动态分配了内存空间来存储序列化的数据。

2. 将 char* 转换为结构体(反序列化)

反序列化是将字节流(char*)解析回结构体。你需要确保字节流的内容与目标结构体的格式完全匹配。

示例代码:

#include<iostream>#include<cstring>// 用于 memcpy// 定义一个结构体structMyStruct{intid;floatvalue;charname[50];};intmain(){// 创建一个结构体实例MyStruct myStruct={123,45.67f,"Example"};// 将结构体内容复制到一个 char* 数组(字节流)char*buffer=newchar[sizeof(MyStruct)];std::memcpy(buffer,&myStruct,sizeof(MyStruct));// 反序列化:将 char* 转换回结构体MyStruct newStruct;std::memcpy(&newStruct,buffer,sizeof(MyStruct));// 输出反序列化后的结构体内容std::cout<<"Deserialized struct: "<<std::endl;std::cout<<"id: "<<newStruct.id<<std::endl;std::cout<<"value: "<<newStruct.value<<std::endl;std::cout<<"name: "<<newStruct.name<<std::endl;// 释放内存delete[]buffer;return0;}

解释:
我们再次使用 memcpy 将 char* 缓冲区中的字节数据拷贝回结构体。
std::memcpy(&newStruct, buffer, sizeof(MyStruct)) 将字节流反序列化成 MyStruct 结构体。
反序列化之后,我们可以通过结构体的成员访问数据。

3. 使用 std::string 替代 char*

现代 C++ 推荐使用 std::string 来处理字符串和字符数组,这样可以避免手动管理内存和可能的缓冲区溢出问题。如果结构体中包含字符串,你可以将 std::string 作为成员来简化管理。

示例代码:

#include<iostream>#include<string>structMyStruct{intid;floatvalue;std::string name;// 使用 std::string 代替 char[]};intmain(){// 创建一个结构体实例MyStruct myStruct={123,45.67f,"Example"};// 将结构体转换为字节流(序列化)size_t size=sizeof(myStruct.id)+sizeof(myStruct.value)+myStruct.name.size()+1;char*buffer=newchar[size];// 手动将各个成员复制到字节流memcpy(buffer,&myStruct.id,sizeof(myStruct.id));memcpy(buffer+sizeof(myStruct.id),&myStruct.value,sizeof(myStruct.value));memcpy(buffer+sizeof(myStruct.id)+sizeof(myStruct.value),myStruct.name.c_str(),myStruct.name.size()+1);// 输出序列化后的字节流内容std::cout<<"Serialized buffer content: ";for(size_t i=0;i<size;++i){std::cout<<static_cast<int>(buffer[i])<<" ";}std::cout<<std::endl;// 反序列化:从字节流恢复结构体MyStruct newStruct;memcpy(&newStruct.id,buffer,sizeof(newStruct.id));memcpy(&newStruct.value,buffer+sizeof(newStruct.id),sizeof(newStruct.value));newStruct.name=std::string(buffer+sizeof(newStruct.id)+sizeof(newStruct.value));// 输出反序列化后的结构体内容std::cout<<"Deserialized struct: "<<std::endl;std::cout<<"id: "<<newStruct.id<<std::endl;std::cout<<"value: "<<newStruct.value<<std::endl;std::cout<<"name: "<<newStruct.name<<std::endl;// 释放内存delete[]buffer;return0;}

解释:
std::string 是 C++ 提供的安全字符串类,自动管理内存,因此使用它可以避免手动处理 char* 的问题。
我们依然手动进行序列化和反序列化,但 std::string 使得字符串操作更加简单和安全。

  • 总结
    序列化(结构体转 char*):使用 memcpy 将结构体的内存内容拷贝到一个字节数组中。
    反序列化(char* 转结构体):使用 memcpy 将字节流中的内容恢复回结构体。
    现代 C++ 更推荐使用 std::string 来处理字符串,避免使用低级的 char* 类型。

4、结构体转换为char*的其他写法

  • 方法一:强转
  • 方法二:reinterpret_cast
    reinterpret_cast 是 C++ 中用于类型转换的操作符,允许在不同类型之间进行低级别的指针转换(例如,将一个结构体指针转换为 char*)。它不会对转换进行任何类型安全的检查,因此适合用于底层的指针转换。
#include<iostream>#include<cstring>// 用于 memcpy// 定义一个结构体structMyStruct{intid;floatvalue;charname[50];};intmain(){// 创建一个结构体实例MyStruct myStruct={123,45.67f,"Example"};// 将结构体内容复制到一个 char* 数组(字节流)char*buffer=newchar[sizeof(MyStruct)];std::memcpy(buffer,&myStruct,sizeof(MyStruct));// 输出字节流的内容std::cout<<"Serialized buffer content: ";for(size_t i=0;i<sizeof(MyStruct);++i){std::cout<<static_cast<int>(buffer[i])<<" ";}std::cout<<std::endl;char*buf=(char*)&myStruct;if(memcmp(buffer,buf,sizeof(MyStruct))==0)std::cout<<"buffer and buf is same\n";char*buf2=reinterpret_cast<char*>(&myStruct);if(memcmp(buffer,buf2,sizeof(MyStruct))==0)std::cout<<"buffer and buf2 is same";// 释放内存delete[]buffer;return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 5:36:16

欧拉角实现原理

一句话&#xff1a;欧拉角就是把任意一个旋转&#xff0c;拆成"绕 3 根轴依次转 3 次"。 记录的只是 3 个角度&#xff0c;真正旋转物体时&#xff0c;会把它们变成 3 个旋转矩阵按顺序相乘。还是按 直觉 → 原理 → 代码 → 坑 的顺序&#xff0c;尽量讲简单。一、直…

作者头像 李华
网站建设 2026/10/17 5:36:14

小世界网络+多智能体:如何用AI头脑风暴挖掘AI风险?

1. 从标题拆解入手&#xff1a;这个项目到底在做什么“Small-world Networks of Agents Brainstorm AI Risks to Support Ideation”这个标题&#xff0c;第一次读会觉得有点绕。拆开来看&#xff0c;核心其实就三块&#xff1a;小世界网络、智能体头脑风暴、AI风险构思支持。翻…

作者头像 李华
网站建设 2026/10/17 5:34:33

Codex AI编程智能体详解:从安装配置到接入DeepSeek及报错排查

最近这半年&#xff0c;AI 编程圈子里热度涨得最快的名字&#xff0c;除了 Claude Code&#xff0c;就是 Codex。我后台收到的私信里&#xff0c;一大半都在问&#xff1a;Codex 到底怎么装、怎么登录、怎么接入 DeepSeek、为什么一跑就报错。正好 VideCoding 这个系列第一期&a…

作者头像 李华
网站建设 2026/10/17 5:34:23

无虚拟化环境下安装Docker:Windows容器与远程主机两种方案

如果你在一台硬件虚拟化没开启的 Windows 机器上装过 Docker Desktop&#xff0c;大概率会遇到一个很尴尬的场景&#xff1a;安装界面一切正常&#xff0c;跑起来之后各种“虚拟化已禁用”的提示就冒出来了。尤其是公司的老办公机、部分云主机里的 Windows 系统&#xff0c;或者…

作者头像 李华
网站建设 2026/10/17 5:34:23

图转PPT:绕过AI语义瓶颈的高保真交付新路径

1. 为什么“AI一键生成PPT”至今没人敢说真正落地&#xff1f;“用AI一键生成PPT”这八个字&#xff0c;过去三年在办公软件发布会、自媒体标题、销售话术里高频出现&#xff0c;几乎成了效率工具的标配宣传语。但如果你真把这句话当真——打开某款标榜“输入一句话&#xff0c…

作者头像 李华