1、结构体
基本语法:
//声明结构体
struct MyStruct
{
char *name;
int size;
};
//创建结构体
struct MyStruct myStruct = {"TidusWW", 100};
myStruct.name = "tidus";
myStruct.size = 20;
可使用.
语法直接访问结构体中的成员。
结构体重命名:
//声明的时候
typedef struct _MyStruct
{
char *name;
int size;
} MyStruct;
//或者在基本语法声明之后
typedef struct _MyStruct MyStruct
//创建结构体
MyStruct myStruct = {"TidusWW", 100};
使用typedef struct [oldName] [newName]
语法让结构体获得别名,让使用更简单。
结构体指针:
下面例子中,执行myStruct2 = myStruct1
语句后,myStruct2将会是myStruct1的一份拷贝。
MyStruct myStruct1 = {"TidusWW", 100};
MyStruct myStruct2 = myStruct1;
myStruct2.size = 20;
printf("myStruct1.size:%d, myStruct2.size:%d", myStruct1.size, myStruct2.size );
//输出:只有myStruct2的size被改变了
//myStruct1.size:100, myStruct2.size:20
可以使用MyStruct *myStruct2 = &myStruct1
语句,创建指向myStruct1地址的myStruct2结构体指针。并使用->
语法访问结构体指针中的成员,代码如下。
MyStruct myStruct1 = {"TidusWW", 100};
MyStruct *myStruct2 = &myStruct1;
myStruct2->size = 20;
printf("myStruct1.size:%d, myStruct2.size:%d", myStruct1.size, myStruct2->size );
//输出:myStruct1的size也被改变了
//myStruct1.size:20, myStruct2.size:20
另外可以通过malloc()
函数直接创建结构体指针,通过free()
函数释放指针
MyStruct *myStructP = malloc(sizeof(MyStruct));
free(myStructP);
结构体大小
结构体所占用的内存大小受它的成员类型以及成员的排列顺序影响。
//总长度为3
typedef struct _Len
{
int8_t int1;//1
int8_t int2;//1
int8_t int3;//1
} Len;
类型相同时,长度简单相加,为3。
//长度为12
typedef struct _Len
{
int8_t int1;//1
int8_t int2;//1
int32_t int3;//4
int8_t int4;//1
} Len;
长度不同时,结构体中的内存分配将会按照长度最大的成员的长度倍数进行,且成员在内存中的分布不能跨越任意一个内存块(根据成员中最大的长度而定),这样可以保证在对结构体的成员所在的内存进行存取时性能不受影响,这种做法叫做内存对齐。
例如上面的结构体Len,最大长度的成员是int32_t,长度为4,故分配给结构体的内存大小将是4的倍数。前4个字节用于存放int1和int2,当存放int3时虽然还有2个字节的空间,但为了不夸越内存块,会再开辟4个字节的内存存放int3,然后再次开辟4个字节存放剩下的int4,总长度为12。
虽然这样子可以加快内存的访问存取速度,但会占用更多的空间,在网络传输的情境下如果需要对结构体进行传输,这种方式会造成不必要的流量浪费,可以用下面的方式声明结构体,使结构体不使用内存对齐的方式来保存。
//长度为7
typedef struct _Len
{
int8_t int1;//1
int8_t int2;//1
int32_t int3;//4
int8_t int4;//1
}__attribute__((__packed__)) Len;
2、共同体
共同体:
结构体中的成员在内存中是平铺的,每个成员都有自己的独立的内存空间,共同体中的成员则是共用一块内存的,其占用内存的大小是共同体中所占空间最大的成员的类型长度。
创建语法和结构体差不多,代码如下:
typedef union _BaseData
{
char data;
uint8_t dataNum;
} BaseData;
//创建共同体
BaseData data1;
data1.data = 'A';
printf("data1.dataNum:%d\n", data1.dataNum);
printf("data1.len:%ld\n", sizeof(BaseData));
//输出
data1.dataNum:65
data1.len:1//成员中类型最长的长度为1
上面给共同体data1的data成员赋值'A',由于'A'在内存中就是以0x41保存,其十进制就是65,所以当输出和data成员共用同一份内存的dataNum时,结果就是65。
如果给共同体添加一个uint32_t
类型的成员,共同体的长度会变成4:
typedef union _BaseData
{
char data;
uint8_t dataNum;
uint32_t size32;
} BaseData;
//创建共同体
BaseData data1;
data1.data = 'A';
printf("data1.dataNum:%d\n", data1.dataNum);
printf("data1.len:%ld\n", sizeof(BaseData));
//输出
data1.dataNum:65
data1.len:4//成员中类型(uint32_t)最长的长度为4Byte