结构体,位段,枚举,*联合体入门

结构体

1、匿名结构体

2、结构体指针

3、结构体类型重命名

*4、结构体内存对齐

匿名结构体

匿名结构体就是在创建结构体的时候没有给予结构体命名

struct {
	int a;
	char b;
}x;

这样的结构体,我们称为匿名结构体,匿名结构体在使用时只可以使用一次。

结构体指针

数据结构中经常用到定义和本身结构体命名相同的结构体指针

struct Node{
	int data;
	struct Node* next;
};

next是类型为(struct Node*)的结构体指针,为什么要这么命名呢,就好像函数的递归一样,函数的递归是调用函数自身,那么在结构体这里就是指向结构体内部类型一样的结构体,这里我用画图表示。

在主函数中创建结构体指针的用法

struct stu{
	char name[20];
	int age;
};

int main(){
	struct stu *p=NULL;
	struct stu s;
	p=&s;
}

把创建的结构体地址赋值给结构体指针p,结构体指针只能指向结构体

下面是如何使用结构体指针的方法

int main(){
	struct stu *p=NULL;
	struct stu s;
	p=&s;
	char arr[20]={"zhangsan"};
	strcpy(p->name,arr);
	printf("%s\n",p->name);
	p->age=10;
	printf("%d",p->age);
}

其中的p->name也可以替换成(*p).name

这里也顺便区分一下' -> '和' . '

这里我们暂且使用上面的结构体:struct stu

创建结构体:struct stu s;

创建结构体指针:struct stu *p=NULL;

使用结构体时通常都是s.name  ||  s.age

但是使用结构体指针时是p->name ||  p->age  ||  (*p).name  ||  (*p).age

结构体类型重命名(typedef)

typedef struct student{
	char name[20];
	int age;
}stu;

这里我们创建一个结构体,且使用typedef

那么在主函数中使用有什么区别呢

int main(){
	student stu;
	stu.age=10;
	printf("%d",stu.age);
}

创建结构体时就不要在前面加上struct了

就可以看成是stu把struct student给替换了

结构体内存对齐

结构体内存对齐就是结构体在内存中的存储方式

特点:浪费了一定的空间,但是提升了读取效率。

首先我给出一个结构体

struct s1{
    double a;
	char b;
    int c;
};

在不考虑系统默认对齐数的情况下

 double类型数据占8个字节,占据的空间必须是8的倍数的地址空间,比如0~7、 8~15、16~23

char类型数据大小为1个字节,所以可以任意存放

int类型数据4个字节,必要要存放在4的倍数的地址空间只能存在12~15

所以该结构体大小是16字节

对齐数

对齐数是结构体内存对齐的重要内容,直接影响到结构体的大小

Visual Studio的对齐数默认是8。

没有默认对齐数时取结构体中数据类型最大的:double类型: 8字节   long long: 8字节

结构体的大小必须是对齐数的整数倍。

这里我们简单举一个例子

从上图中我们截取一部分,如果内存对齐数改为4,那么该结构体的大小是12字节

如果对齐数是8,结构体的大小依旧是16

#pragma pack(4)

加入该代码可以修改系统的默认对齐数。

 位段

位段的成员名后面必须有一个冒号和数字

数字代表该成员所占的bit位

struct A{
	int a:2;  //占2个bit位 
	int b:5;   //占5个bit位 
	int c:10;   //占10个bit位 
};

该位段的大小为17个bit位

由于是int类型,开辟空间时开辟了4个字节(32个bit位)

上图是位段成员在内存中的存放方式

下面我们分析这样一个位段:

struct _Record_Struct
{
  unsigned char Env_Alarm_ID : 4;
  unsigned char Para1 : 2;
  unsigned char state;
  unsigned char avail : 1;
};

unsigned char是大小为一个字节的无符号字符型

该位段占据了3个字节大小的空间

因为state后面没有加上冒号和数字,所以state就是unsigned char类型的成员变量,大小一个字节

且在空间分隔了两个位段空间。

枚举(enum)

枚举简单易懂,看两段代码就能理解

enum S1{
	exit,
	add,
	sub,
	mul,
	div,
	sort
};
#define exit 0
#define add 1
#define sub 2
#define mul 3
#define div 4
#define sort 5

枚举中的第一个数子默认从0开始,然后不断加1

当其中有一个变量被赋值成其他值时

enum S1{
	exit,
	add,
	sub,
	mul=10,
	div,
	sort
};

用define来解释通俗易懂

#define exit 0
#define add 1
#define sub 2
#define mul 10
#define div 11
#define sort 12

mul别赋值为10,那么mul下面的变量就在10的基础上+1

*联合体(union)

联合体的大小取决于联合体内成员变量中最大的那个

union un {
	int a;
	char b;
};

这样一个联合体,他的大小取决于int类型的变量;

因为在联合体中,a和b公用一块空间

#include<stdio.h>
union un {
	int a;
	char b;
};
int main() {
	union un n;
	printf("%p\n", &(n.b));
	printf("%p\n", &(n.a));
	n.b = 'a';
	printf("%c\n", n.b); 
	printf("%c\n", n.a);
	n.a = 20;
	printf("%d\n", n.b);
	printf("%d\n", n.a);
}

这时候打开调试,我们看一看内存中的变化。

运行这一段代码的时候会发现,为什么n.a和n.b不但地址相同,而且改变其中一个,另一个也会随之改变。这已经说明了a和b公用一块空间,且同一时间,只能使用其中一个。

那么char和int的区别在哪??

假如我把整数改成500会发生变化吗???

很仔细了解释了 为什么输入500时,输出的结果有那么大的差异

首先一个字节有符号数的大小为(-128~127)

当超过这个值时,一个字节已经无法放下他,但是取值时我们仍然只能取8个bit位。

这是用1个字节存4个字节整数的问题。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值