typedef struct结构体总结篇

本文详细介绍了C语言中结构体与指针的基本概念和使用方法,包括如何定义结构体、如何通过指针操作结构体成员变量,并提供了具体的代码示例。
#include <stdio.h>
void  test(void);

//1、用typedef struct student{类型 变量名}STU,*STU1,在{}后面跟的STU是该结构体的变量名,*STU1是该结构体的类型的地址。
typedef struct student{
    int age ;
}STU ,*STUP;
/*
 上面的和下面的等价
 typedef struct student{
 int age ;
 }STU;
 typedef STU *STUP;
 */
int main(int argc, const char * argv[]) {
    //声明一个结构体对象
    STU opooc;
    //声明一个指向该类结构体对象的指针
    STUP opoocP ;
    //给结构体对象内部age变量赋值,用 . 语法
    opooc.age = 10;
    //给指针赋值(这里赋值的是该结构体类型对象的地址)
    opoocP = &opooc;
    //给所指向结构体变量对象的内部age修改值。对于指针,用 -> 语法
    opoocP->age = 20;
    return 0;
}
//2、下面两种可以直接用 struct student2 和struct student3声明变量
struct studen2{
    int age ;
};
typedef struct student3{
    int age ;
};
//3、用struct student{类型 变量名}stu,*stu;在{}后面跟的stu是struct student的结构体对象,*stu是指向该种结构对象的指针;
struct teacher{
    int class;
}teacher1,*teacherP;
void  test(){
    //给对象赋值
    teacher1.class = 1;
    //这里还可以根据结构体类型继续声明结构体对象。
    struct teacher teacher2;
    return ;
}
//4、直接改名
typedef struct{
int class;
}stu;





<think> 我们正在处理一个关于C/C++结构体与Qt的QByteArray转换的问题。 用户希望将typedef struct定义的结构体转换为QByteArray。这通常用于网络传输或文件存储等场景。 步骤: 1. 确保结构体是POD(Plain Old Data)类型,即没有虚函数、没有非静态的非POD成员等,以保证内存布局是连续的且没有填充(或填充可控)。 2. 使用reinterpret_cast将结构体指针转换为char*(或const char*),然后利用这个指针和结构体的大小来构造QByteArray。 注意事项: - 由于结构体可能有内存对齐导致的填充字节,不同平台或编译器设置可能导致结构体大小不同。因此,需要确保发送端和接收端使用相同的编译器和相同的对齐设置(#pragma pack等)。 - 如果结构体包含指针或非POD类型,则不能直接进行内存拷贝,因为指针指向的内容不会被复制,而且指针值在另一个进程或机器上无效。 示例代码: 假设有以下结构体typedef struct { int a; char b; double c; } MyStruct; 转换为QByteArray: MyStruct s; // 填充s的成员... QByteArray byteArray(reinterpret_cast<const char*>(&s), sizeof(MyStruct)); 但是,如果结构体包含动态分配的数据(如指针)或复杂类型(如std::string),则不能使用上述方法。此时需要序列化(例如使用QDataStream)。 对于非POD结构体,建议使用序列化方法。Qt提供了QDataStream来序列化数据。 使用QDataStream的示例: QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream << s.a << s.b << s.c; 但是,这要求结构体的每个成员都是Qt知道的基本类型或已注册的自定义类型。如果结构体很复杂,可能需要重载<<和>>操作符。 由于用户提到的是typedef struct,我们假设结构体是POD类型。 因此,如果结构体是POD,可以直接内存拷贝;否则,需要手动序列化。 另外,如果需要将QByteArray再转换回结构体,同样需要注意上述问题。 转换回结构体的方法: const MyStruct* s = reinterpret_cast<const MyStruct*>(byteArray.constData()); // 注意:这里只是获取了一个指向QByteArray内部数据的指针,并没有复制。如果要修改,应该先复制一份。 或者: MyStruct s; if (byteArray.size() == sizeof(MyStruct)) { memcpy(&s, byteArray.constData(), sizeof(MyStruct)); } 考虑到平台兼容性,建议在结构体定义时使用1字节对齐,以避免不同平台对齐方式不同导致的问题。 使用#pragma pack(1)的例子: #pragma pack(push, 1) typedef struct { int a; char b; double c; } MyStruct; #pragma pack(pop) 这样,结构体在内存中就是紧密排列的,没有填充字节,不同平台上的大小一致。 总结: 方法1(直接内存拷贝,适用于POD且注意对齐): QByteArray byteArray(reinterpret_cast<const char*>(&myStruct), sizeof(MyStruct)); 方法2(使用QDataStream序列化,更通用): QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); // 逐个写入结构体成员 stream << myStruct.a << myStruct.b << ...; 根据结构体的复杂程度选择合适的方法。 生成相关问题: 1. 如何确保结构体在不同平台上的内存布局一致? 2. 如果结构体包含指针,应该如何转换为QByteArray? 3. 如何使用QDataStream序列化自定义结构体? 4. 如何将QByteArray转换回结构体? 5. 结构体对齐设置#pragma pack的使用方法是什么? </think> 要将 `typedef struct` 定义的结构体转换为 `QByteArray`,主要涉及内存数据的直接拷贝。以下是具体步骤和注意事项: --- ### **步骤** 1. **确保结构体是POD类型** - 结构体必须是**平凡数据类型(Plain Old Data)**: - 无自定义构造函数/析构函数 - 无虚函数或虚基类 - 所有成员均为POD类型(如基本类型、数组、其他POD结构体) ```c #pragma pack(push, 1) // 禁用内存对齐填充(确保跨平台一致性) typedef struct { int id; char name[32]; float value; } MyStruct; #pragma pack(pop) ``` 2. **转换为 `QByteArray`** 使用 `reinterpret_cast` 将结构体指针转为 `char*`,并指定数据长度: ```cpp MyStruct data = {42, "Example", 3.14f}; QByteArray byteArray(reinterpret_cast<const char*>(&data), sizeof(MyStruct)); ``` 3. **反向转换(从 `QByteArray` 恢复结构体** 通过内存拷贝还原数据: ```cpp QByteArray receivedArray = ...; // 接收到的QByteArray if (receivedArray.size() == sizeof(MyStruct)) { MyStruct recoveredData; memcpy(&recoveredData, receivedArray.constData(), sizeof(MyStruct)); } ``` --- ### **注意事项** 1. **内存对齐问题** - 使用 `#pragma pack(1)` 禁用编译器填充,避免不同平台/编译器导致的结构体大小不一致。 - 验证 `sizeof(MyStruct)` 确保与实际内存匹配。 2. **字节序(Endianness)** - 若跨设备传输(如网络),需处理字节序: ```cpp QDataStream stream(&byteArray, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); // 或 BigEndian stream << data.id << QString::fromUtf8(data.name) << data.value; ``` 3. **非POD类型的替代方案**结构体包含非POD成员(如 `QString`),需手动序列化: ```cpp QByteArray serialize(const MyStruct &s) { QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream << s.id << s.name << s.value; return array; } ``` --- ### **完整示例** ```cpp #include <QByteArray> #include <QDataStream> #pragma pack(push, 1) typedef struct { int id; char name[32]; float value; } MyStruct; #pragma pack(pop) // 转换为 QByteArray QByteArray structToByteArray(const MyStruct &data) { return QByteArray(reinterpret_cast<const char*>(&data), sizeof(MyStruct)); } // 从 QByteArray 恢复 MyStruct byteArrayToStruct(const QByteArray &array) { MyStruct data; if (array.size() == sizeof(MyStruct)) memcpy(&data, array.constData(), sizeof(MyStruct)); return data; } ``` --- ### **关键点总结** | 方法 | 适用场景 | 优点 | 缺点 | |--------------------|--------------------------|--------------------------|--------------------| | 直接内存拷贝 | POD结构体 | 高效,代码简单 | 依赖内存布局一致性 | | `QDataStream` | 含非POD成员或需跨平台 | 自动处理字节序和类型安全 | 速度稍慢 | [^1]: 基于Qt文档中QByteArray和内存操作的说明。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值