自定义类型(struct结构体)

本文深入探讨C语言中结构体的创建、初始化、内存对齐、位段及枚举联合的使用技巧。从结构体的基本定义到高级特性,全面解析结构体在C编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.结构体类型创建
(1)常用创建推荐用这种

struct  Student{   //里面是各种信息
int  age;
char  gender;
float  score;’
};
struct Student s;  // 定义结构体变量

(2)

typedef struct  Student{   //里面是各种信息
int  age;
char  gender;
float  score;
}student;


它更方便使用或建立结构体变量,直接这样:
student s; // s就是一个结构体变量

(3)匿名结构体(基本没用)

struct {   //里面是各种信息
int  age;
char  gender;
float  score;
}s;

2.结构体初始化
一般在定义结构体变量时直接进行初始化,或者通过指针指向。

struct  Student{   //里面是各种信息
int  age;
char  gender;
float  score;
};

struct Student s = {12,“李楠”,100};  // 定义结构体变量
s.score = 80;
struct Student *p = &s;
p -> score = 70;
(*p). score = 30;

先定义在初始化不行例如
struct Student s;
s = {12,“李楠”,100};   // 这样不行

3.结构体内存对齐

要满足4大原则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。
例如 vs中默认值为8
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自已的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

来看一个简单的例题

struct Test{
char a; //a 放在偏移为 0 的 位置上
int b; // b  (8 > 4) => 4 放在偏移量为 4 的整数倍上,则应放在 4上 则 前面浪费了3个字节
char c;c  (8 > 1) => 1 放在偏移量为 1 的整数倍上。
}Test;

他在内存中的图应该为:
在这里插入图片描述
这样看他就有12个字节了
而且结构体的对齐数可以手动修改,这样默认值就可以挨在一起了。

#pragma pack(1)  //这样默认值为1 全连着放也是有多少字节就有多大内存
struct Test{
char a; //a 放在偏移为 0 的 位置上
int b; // b  (8 > 1) => 1 放在偏移量为 1 的整数倍上
char c;c  (8 > 1) => 1 放在偏移量为 1 的整数倍上。
}Test;
#pragma pack()   //还原默认值

4.位段,位段计算机大小
位段:成员必须是int 、unsigned int 和signed int .
位段的成员名后边有一个冒号和一个数字。
计算:位段是按比特位的大小来进行计算的,比如一个字节有8个比特位,存入的时候根据数据类型的不同计算出相应的比特位依次往后存储,若存储不下则开辟下一个字节

 struct Test
    {
    int  a:4;
    int  b:5;
    int  b:6;
    int  b:30;
   };
   s就是一个位段类型
   printf("%d\n",sizeof(struct S));//8
   分析:int 型具有四个字节,共32个比特位,故存储时将前三个放入第一块空间中,由于第四个是30个比特位存储不下,因此开辟下一快空间存储,即开辟了两快空间,就是好8个字节。其他类型同理可得。

5.枚举+联合
(1)枚举

enum color
{
red;
orange;// 2
yellow = 3;
green;// 4
blue;
};
枚举常量默认值从0开始,依次递增一,在定义时也可赋初值。
enum color purple=blue;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。

(2)联合
是一种特殊的自定义类型,特征是这些成员公用同一块空间(所以联合也叫共用体)。

union Un
    {
        char c;
        int i;

    };
    union Un A;
    printf("%d\n",sizeof( A));//4
<think>好的,我需要解决用户的问题:如何将自定义的C++ struct结构体注册并传递给QML使用。首先,我得回忆一下Qt中关于C++和QML交互的相关知识。 根据用户提供的引用内容,引用[1]提到C++和QML之间的信号传递只支持基本类型,但用户希望传递自定义结构体。引用[2]和[3]提到了注册结构体到元对象系统和使用setContextProperty的方法。所以可能的步骤包括:定义结构体,注册到Qt的元对象系统,暴露给QML,可能需要使用Q_GADGET宏而不是Q_OBJECT,因为结构体不能继承QObject。 接下来要确保结构体有正确的属性和元对象支持。使用Q_GADGET可以让结构体具有元对象功能,这样QML就能识别它的属性。然后,通过qmlRegisterType或者setContextProperty将结构体实例暴露到QML上下文中。另外,需要注意数据类型的转换,可能需要使用QVariant或者注册为元类型。 可能遇到的问题包括结构体属性无法在QML中访问,或者信号传递时类型不匹配。需要检查是否正确注册了元类型,以及是否在QML中正确引用了结构体实例。此外,如果结构体包含复杂类型,可能需要进一步处理,比如使用QVector时需要注册对应的元类型。 总结步骤应该是:定义结构体并添加Q_GADGET,注册为元类型,设置上下文属性或注册为QML类型,最后在QML中使用。需要验证每个步骤的正确性,确保属性和方法都能被QML访问到。</think>### 分步解答:将自定义C++结构体集成到QML使用 #### 1. 定义结构体并添加元对象支持 在C++中定义结构体时,需添加$Q_GADGET$宏和$Q_PROPERTY$声明以暴露属性到QML: ```cpp #include <QObject> #include <QString> struct MyStruct { Q_GADGET // 替代Q_OBJECT(适用于非QObject派生类) Q_PROPERTY(int id MEMBER id) // 注册id属性 Q_PROPERTY(QString name MEMBER name) // 注册name属性 public: int id = 0; QString name = ""; }; ``` #### 2. 注册结构体到Qt元对象系统 在程序初始化阶段(如main函数),通过以下步骤注册: ```cpp // 注册结构体为元类型 qRegisterMetaType<MyStruct>("MyStruct"); // 创建实例并绑定到QML上下文 QQmlApplicationEngine engine; MyStruct myInstance; engine.rootContext()->setContextProperty("myStruct", &myInstance); // [^2] ``` #### 3. 在QML中访问结构体属性 通过注册的上下文属性名称直接访问: ```qml Text { text: "ID: " + myStruct.id + ", Name: " + myStruct.name } ``` #### 4. 处理复杂类型传递(如信号/槽) 若需通过信号传递结构体,需额外注册: ```cpp qRegisterMetaType<MyStruct>("MyStruct"); qmlRegisterType<MyStruct>("MyModule", 1, 0, "MyStruct"); // [^3] ``` ### 注意事项 - 使用$Q_GADGET$时必须保证结构体**不含虚函数表**,否则会导致QML访问失败 - 容器类型(如$QVector<MyStruct>$)需单独注册: `qRegisterMetaType<QVector<MyStruct>>("QVector<MyStruct>");` - 属性修改需通过**显式信号通知**QML更新界面[^1] ### 完整示例流程 ```cpp // main.cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> struct MyStruct { Q_GADGET Q_PROPERTY(int value MEMBER m_value NOTIFY valueChanged) public: int m_value = 0; signals: void valueChanged(); // Q_GADGET支持信号声明 }; Q_DECLARE_METATYPE(MyStruct) int main(int argc, char *argv[]) { qRegisterMetaType<MyStruct>("MyStruct"); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyStruct instance; engine.rootContext()->setContextProperty("myStruct", &instance); return app.exec(); } ``` ```qml // main.qml Button { onClicked: { myStruct.m_value += 1 console.log("Current value:", myStruct.m_value) } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值