C结构体

结构体是使用其他类型组合的类型.

定义

语法:

struct 结构体标签
{
    类型1 成员1;
    类型2 成员2;
    类型n 成员n;
}

结构体可以包含多个成员,每个成员有自己的名称,可以是不同类型。

完整的结构体类型名称是struct 结构体标签.

struct tag_point
{
    int x;
    int y;
}

结构体别名

可以为结构体定义别名,简化使用。

定义结构体别名

typedef struct tag_point point;

同时定义结构体和别名

typedef struct tag_point
{
    int x;
    int y;
}point;

结构体声明

语法:

类型 变量名 = {成员1,成员2,成员n}
point p1;//不初始化
point p2 = {1,2};//全部初始化
point p3 = {1};//部分初始化
point p4 = {0};//全部初始化为0

操作结构体成员

语法

变量.成员
point p;
p.x = 10;
p.y = -1;

使用结构体成员和一般变量一致。

匿名结构体

某些结构体只使用一次,可以不设置名称,直接定义变量。

struct
{
    int x;
    int y;
}p1,p2;

自引用的结构体

在实现链表和树结构时,结构体的成员可能是自身类型。

typedef struct tag_node
{
    struct tag_node *next;
}node;

自引用时,在结构体成员中的类型不能使用别名。

访问结构体指针的成员

语法:

变量->成员
point p;
point *pp=&p
pp->x = 10;
pp->y = -1;

pp->x等价于(*p).x,前者使用更方便。

结构体对齐

为了提高访问效率,结构体中的成员在内存中的结构会按照一定字节数量对齐。

typedef struct tag_person
{
    int age;
    double height;
    char gender;
}person;
int n = sizeof(person);

如果紧密排列person占用字节应该是4+8+1=13,而在8字节字节对齐的情况,结果是24.

编译后的代码并没有结构体信息,只有各个字段的偏移信息。

可以使用#pragma pack(n)设置对齐数量。不同编译器可能有不同的设置方式。

结构体的二进制兼容

如果结构体提供给第三方使用,需要确保双方使用一致的对齐数量,否则会访问错乱。

如果结构体提供给第三方使用,那么修改顺序会影响对成员的访问。第三方程序必须重新编译引用该结构体的代码。

嵌套结构体

结构体的成员也可以是结构体。

typedef struct
{
    point start;
    point end;
}line;

位域

结构体的成员可以使用特定数量的位。

语法:

struct 结构体名称
{
    类型1 成员1:位数1;
    类型2 成员2:位数2;
    类型n 成员n:位数n;
}
typedef struct
{
    int a:4;
    int :4;//忽略的位
    int b:7;
    int c:1;
    int d:16;//这里用完了第一个int的所有位
    int e:1;//这里使用了新的int存放位
    short f:4;//类型和上面的位域不一致,使用了新的short存放位
    int g;//常规成员
}bits;

上述结构体占用空间为:4+4+2+4。当8字节对齐时,需要16个字节。

使用位域

位域的使用和一般结构体相似。区别是:

bits b = {0};
b.a = 10;

共用体

公用体和结构体的定义相似,不过共用体的每一个成员都指向同一个地址。

共用体的定义

语法:

union 结构体名称
{
    类型1 成员1;
    类型2 成员2;
    类型n 成员n;
}

共用体占有字节由占用字节最大的成员决定,需要考虑对齐。

共用体作用

多种访问形式

typedef struct tag_argb
{
    char a;
    char r;
    char g;
    char b;
}argb;

typedef union tag_color
{
    int c;
    argb v;
}color;
color c = {0};

c.v.r = 100;
c.v.g = 200;
c.v.b = 150;

printf("%d\n",c.c);

多种访问形式,需要了解每个成员之间的字节关系。

节约空间

有时候,结构体的某个成员在不同的情况下,有不同含义。

这是,可以使用共用体作为结构体的成员,节约空间。