0%

c语言struct和union

老子曰:道生无,无生有,有生万物。某子曰:机器生汇编,汇编生B,B生C,C生万物。

一、结构体struct

      结构体是由一批数据组合而成的一种新的数据类型,组成结构型数据的每个数据称为结构型数据的“成员”,这些成员可以具有不同的数据类型。由于结构体数据的成员类型不同,因此结构体要由用户在程序中自己定义。
      结构体是一种构造类型,是由若干成员组成的。每一个成员可以是一个基本数据类型(整型、字符型、浮点型),也可以是一个构造类型(结构体、共用体、数组)。

在定义结构体时其成员并不分配内存,只有用struct结构体名来定义该结构型的变量、数组及指针变量时才会分配内存。

结构体本身只是用户定义的一个数据类型,不占用什么存储空间,定义结构体变量以后,系统为其分配一定的存储空间,它在内存中是一个连续的内存单元,总字节数等于该结构型的所有成员所占用的字节数之和。

  1. 定义一个结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
struct unknown
{
  int a;
  char b;
  int c;
  long d;
  char e;
};

int main(int argc, char** argv)
{
printf("%lu\n", sizeof(struct unknown)); //output:32
return 0;
}
  1. 计算内存大小

    • 每个成员的偏移量都必须是当前成员所占内存大小的整数倍,如果不是编译器会在成员之间加上填充字节
    • 当所有成员大小计算完毕后,编译器判断当前结构体大小是否是结构体中最宽的成员变量大小的整数倍,如果不是会在最后一个成员后做字节填充
  2. 针对上面的结构体进行计算

    • 成员变量a,偏移量为0,大小为4字节,符合偏移规则第一条
    • 成员变量b,偏移量为4,大小为1字节,符合偏移规则第一条
    • 成员变量c,偏移量为5,大小为4字节,不符合偏移规则第一条
      • 于是在成员b和c间填充三个字节,此时偏移量大小为8,符合偏移规则第一条,继续往下
    • 成员变量d,偏移量为12,大小为8字节,不符合偏移规则第一条
      • 于是在成员c和d之间填充4个字节,此时偏移量为16,符合偏移规则第一条,继续往下
    • 成员变量e,偏移量为24,大小为1字节,符合偏移规则第一条
    • 所有成员大小计算完后,执行偏移规则第二条,最宽的成员是long d占8个字节,当前结构体计算出的大小为25,不符合第二条规则
      • 于是在末尾填充7个字节,总大小为32个字节,满足第二条偏移规则。
    • 到此结构体大小计算结束
  3. 常用于产生柔性数组,即数组大小待定的数组

1
2
3
4
5
struct SoftArray
{
int len;
int array[]; // 仅仅为一个标识符,不占用存储空间
};

二、共同体union

  1. 定义一个结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>
union uni
{
int a;
char b;
long c;
int d[4];
};

int main(int argc, char** argv)
{
printf("%lu\n", sizeof(union uni)); //output:16
return 0;
}
  1. 计算内存大小

    • union的大小就是最大的成员所占空间大小
  2. 针对上面的结构体进行计算

    • int a占4个字节
    • char b占1个字节
    • long c占8个字节
    • int d[4]占16个字节
    • 故union大小为16字节
  3. 大小端问题

    • 小端模式下,低地址存储低位数据
    • 大端模式下,高地址存储低位数据
  4. 成员赋值问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main(int argc, char** argv)
{
union
{
short i;
char a;
}uni;

uni.i = 0x4241;
printf("%x\n", uni.i); // 4241

uni.a = 'a';
printf("%x\n", uni.i); // 4261

return 0;
}

三、对比

  1. 对于union的不同成员赋值,将会对其他成员重写,即原来的成员值就不存在了,而对struct的不同成员赋值是互不影响的。
  2. size大小
    • union只分配最大成员的空间,所有成员共享这个空间,故union的大小就是最大的成员所占空间
    • struct中的每个数据成员有独立的存储空间,struct在分配空间时要遵循内存对齐规则,即根据成员类型不同会存在字节对齐情况,具体对齐标准和机器有关