OC:结构体(struct)/位域/联合体(union)

1,056 阅读3分钟

前言

经常看到各种结构体的定义,项目中又该如何定义和使用结构体呢?

结构体

常见的结构体定义和使用

基本上见到的结构体定义就就这样四种


struct LQStructA {
    bool a;
};

struct LQStructB {
    bool a;
}structB;

typedef struct LQStructC {
    bool a;
}LQStructC;

typedef struct {
    bool a;
}LQStructD;

1.第一种见到的比较少,基本上自己不会用,但的确是定义结构体的一种方式,一般用在需要明确知道自己用的是结构体类型的数据,在C++.h文件中见到的比较多,比如在scoket.h用的都是这种定义。

image.png 这种在自己使用的时候比较麻烦,无法像基础类型一样直接定义,需要带上关键字struct才行,因为struct LQStructA才是一个类型。


    struct LQStructA structA1;
    structA1.a = YES;
    struct LQStructA structA2;
    structA2.a = NO;
    

2.第二种是定义了一个LQStructB类型,而且直接创建了一个结构体,可以直接使用这个结构体了,这中用法一般是用在就只需要创建一个结构体的时候。一般就是只操作structB就行。如果需要在后面还要创建LQStructB也可以创建,创建和第一种一样。


    //一般操作这一个结构体就可
    structB.a = YES;
    structB.a = NO;
    //也可以在创建
    struct LQStructB structB2;
    structB2.a = NO;
    

3.第三种和第四种的定义的所要效果是一样的,都是使用typedef创建别名,然后使用别名创建结构体。这两种在写的代码中都是比较常见的,区别是第三种可以使用struct+结构体名创建结构体,但是第四种只能根据别名创建结构体。两种的意思也不一样,第三种是将struct LQStructC定义为别名LQStructC,第四种是将一个匿名的结构体声明为LQStructD


        //LQStructC 可以使用别名也可以使用 'struct 结构体名'
        LQStructC c1;
        struct LQStructC c2;
        c1.a = YES;
        c2.a = NO;
        //LQStructD 只能使用别名创建
        LQStructD d1;
        d1.a = NO;
        

总结:项目中基本上用第三种或者第四种就可以了。

结构体的继承

OC来源于C++,所以也有C++结构体特性,继承。在.m文件中是无法使用继承的,需要使用.mm文件才能使用结构体继承。


struct LQStructA {
    int a;
};

struct LQStructB:LQStructA{
    int b;
};

struct LQStructC:LQStructB{
    int c;
};


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        struct LQStructC structC;
        structC.a = 100;
        structC.b = 200;
        structC.c = 300;
        NSLog(@"structC空间大小:%lu",sizeof(structC));
        NSLog(@"structC地址:%p",&structC);
        NSLog(@"end");
    }
    return 0;
}


结构体继承和C++几乎就是一模模一样样的,也有privatepublic等。继承后的结构体占用的内存包含了自己和父类的内存大小,排放是先父结构体,然后才是自己。这里用lldb也产看了一下存储结构。

![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bcefcb8d916c4f3f9c5d2f310d6f63ac~tplv-k3u1fbpfcp-watermark.image)

位域

众所周知,一个字节有8位,有些信息在存储时,并不需要占用一个完整的字节,而只需占几位或一位。例如在存放一个只有0和1两种状态成员,用一位二进位即可,目的是节省存储空间。一般用在bool类型。

image.png

联合体

联合和结构体一样都可以定义多种数据类型,也可以嵌套使用,但是联合体内部成员是互斥的,用的是同一片内存空间,所需空间为最大变量所需空间,同一时间有效的只有一个变量。就像下面设置了sb后sa就无用了,联合体适用于二选一或多选情况下使用。

image.png

image.png