结构体内存分配
在定义结构体类型时,自动为结构体分配内存空间;
在分配内存空间时,会找出成员变量中类型最大的作为分配的最小单位;
每个成员的内存空间必须是连续的,不可以跨分配单元;
如果通过宏#pragma pack(1)指定分配单位的大小,在定义结构体上方使用,则根据结构体内部最大的数据结构类型和宏定义值两者最小值来决定内存分配的最小单元.
例如;
#pragma pack(1) //宏定义最小单元为1字节 取值为 1 2 4 8 范围
struct
{
char x;
char y;
char z;
int len; //成员中最大为int类型 4字节
} s0; //相比之下选最小的 1字节
#pragma pack(4) //宏定义最小值为4字节
struct Person
{
long num; //最大为8字节,选择宏定义值 4字节
char name[30]; // 为name分配置的内存大小必须是单位分配大小的倍数 4的倍数 32字节
int age;
char sex;
float score;
char tag; // A, B, C, D
};
结构体-位段
在结构体中以位为单位的成员变量,称为位段.
位段的声明方式:在结构体成员变量后加 : 位数
// 位段不影响结构体分配内存空间的原则
//赋值时,不能超过位段的定义的数据类型的大小,例如,int不超过32位,char不超过8位,超过后自动截断.
位段成员的数据类型必须为int或者char;
一个位段必须存放在一个存储单元(指的是最小内存分配单元-4字节或者char的1字节)内,不能跨两个单元.
#include <stdio.h>
struct led_struct
{
unsigned int led_f0:1; //int最大,所以以4字节为单位
unsigned int led_f1:1;
unsigned int led_f2:1;
unsigned int led_f3:1;
unsigned int led_f4:1;
};
struct {
char a: 7;
short b: 12;
int c: 30;
long d: 63; //在每个分配的单元内从右向左分配,不够时切换到下一个分配单元,此处的分配单元位8字节64位
} s0;
struct {
char a:2;
char :2; // 无意义的位段 用来占位,此处占了两个比特位
char b:3;
}s1;
int main()
{
printf("led _struct size is %ld\n",sizeof(struct led_struct));
//分配了一个int类型4字节的空间大小,没有用完,只用了其中五个bit位
struct led_struct led;
led.led_f0=1;
led.led_f1=1;
printf("led.f0 is %d\n",led.led_f0);
printf("led.f1 is %d\n",led.led_f1);
printf("led.f2 is %d\n",led.led_f2); //f3 没有赋值,所以为0
return 0;
}
共用体
共用体与结构体类似
用union关键字,使用struct定义
特点;
所以成员变量使用同一块内存空间,空间的大小为成员变量中最大的数据类型的大小
所有成员变量的地址和共用体的地址是同一个;
同一个内存段内可以用来存放不同数据类型的成员,不过每次只有一种有效,即为最后一次存放的数据.
#include <stdio.h>
union Data{
char ch;
short a;
int b;
};
int main(){
printf("%ld\n", sizeof(union Data)); // 最大的成员是b,int类型,占4个字节
union Data d1; // 定义共用体的变量
printf("&d1 is %p\n", &d1);
printf("&d1.ch %p\n", &d1.ch);
printf("&d1.a %p\n", &d1.a);
printf("&d1.b %p\n", &d1.b);
return 0;
}
枚举
枚举也是一种构造类型,将变量的值列举出来,变量的值只限构造体范围.
多个枚举值使用逗号分隔,默认第一个的值为0,枚举值列表里的所有枚举值都是常量.
例如:
#include <stdio.h>
enum Color
{
RED = 2, //枚举值本身就是常量,且有序,可以直接赋值,red为2,下一个为3,
BLUE,
GREEN = 5, //下一个为6,7,..
YELLOW,
BLANK,
WHITE
};
int main()
{
enum Color c1 = YELLOW;
printf("c1 = %d\n", c1); // 6
return 0;
}