c语言 自定义类型详解

结构体的声明与调用

一 . 结构体类型的声明
代码如下:
struct S1
{
int a;
char name[20];
double s;
};

该代码表示该结构体中具有一个int类型的成员a,字符串类型的成员name和double类型的成员s。

二. 建立一个结构体对象
代码如下:
struct S1 s1;
改代码为建立一个结构体对象s1,该对象s1可以对结构体内部的成员进行调用。

三. 调用结构体内部的成员并将其赋值
代码如下:
struct S1 s1;//先建立一个结构体对象
s1.a = 4;
s1.name = “zhangsan”;
s1.s = 1.1;

该代码将成员a赋值为4 ,成员name赋值为zhangsan ,成员s赋值为1.1。

将结构体作为另一个结构体的成员

代码如下:
struct S1
{
int c1;
char i;
char c2;
};

struct S2
{
double a;
struct S1 s1;
double m;
};

该代码是把结构体S1作为S2的成员
所以当结构体S2的对象调用S1的时候代码如下:
struct S2 s2;
s2.s1.c1 = 4;
s2.s1.i = ‘C’;
s2.s1.c2 = ‘B’;
该代码就是将S2的对象对S1内对象的调用并赋值。

结构体的内存对齐与位段

一. 结构体的内存对齐

struct S1
{
int c1;//4 因为是第一个所有的第一个都存储到偏移量为0的地方
char i;//1 //所以此时这个char是从偏移量为4的地方开始存储
char c2;//1 //c2从偏移量为5的地方开始存储
//这样存储所消耗的空间为六个字节,因为六个字节不是4的倍数,所以此时要提升到八个字节
};
在上面的代码中对齐数为4,结构体最终求出的所占用的字节数要是对齐数的倍数,对齐数定义如下:

对齐数就是编译器默认的一个对齐数和该成员中所占字节最大的元素的最小值

上面的代码中第一个元素从偏移量为0开始进行存储,因为int占用四个字节,所以当第二个成员进行存储的时候是从偏移量为4开始进行存储,存储后c2是从偏移量为5进行存储存储到最后为六个字节,但是上面的代码中的对齐数是4,所以最后存储的字节数要是对齐数的倍数,所以最后存储的字节数是八个字节。

二. 结构体的位段

#include <stdio.h>
//
struct A
{
//位段
char _a : 3;//表示的是a只需要两个比特位
char _b : 4;
char _c : 5;
char _d : 4;//后面的数字不能超过三十二
};

int main()
{
struct A sa;
//因为结构体元素都是int类型
//所以先开辟一个整型四个字节
//四个字节为三十二位 (被a,b,c所占用了)
//这时候四个字节被占用完了但是元素还没有存储完
//所以这时候再开一个整型四个字节来存储d
//所以此时是开辟了两个整形所以该结构体所占用的空间是8
printf("%d\n", sizeof(struct A));
//此时开辟空间为8
return 0;

}

位段的定义:C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”。

位段的优点:利用位段能够用较少的位数存储数据。

上面的代码中代表将结构体A中的成员a在内存中存储三个比特位,所以可知下面成员b存储四个比特位,成员c存储五个比特位,成员d存储4个比特位。

最后可得该结构体在内存中存储的字节为:
在这里插入图片描述

因为一个字节是八个比特位,并且在该编译器中当一个字节中剩下的比特位不足够来存储其他成员的时候就新开一个字节进行存储其他的成员。

联合体的内存存储

#include <stdio.h>

//联合体
//联合体的大小也要是对齐数的整数倍
union Sex
{
char c;
int i;
};

int main()
{
union Sex u;
u.i = 0x11223344;
u.c = 0x55;
//此时是先将i赋值占用了四个字节
//又将char c进行赋值占用了一个字节
//但是这个是联合体,联合体中元素的起点地址是相同的
//所以c占用的一个字节是i最先占用的字节也就是c把i中的一个字节顶替了
//又因为编译器是由小段的存储方式进行存储所以此时输出u.i就会得到0x11223355
printf("%d\n", sizeof(u));//因为int最大所以联合皮开辟的空间至少是四个字节

printf("%p\n", &u);
printf("%p\n", &(u.c));
printf("%p\n", &(u.i));
printf("%x\n", u.i);
//此时联合体和其元素的地址起点是一个地方
//所以联合体的开辟的空间和其内部元素最大开辟的字节至少相同
//联合体开辟的字节至少和其内部元素最大开辟空间的字节相同
return 0;

}

此代码的结果为:
在这里插入图片描述
由上面所得的值可知在联合体中的成员存储的起始地址是一样的,而且联合体在内存中存储的时候其所占的字节数至少为成员函数中最大开辟的空间,并且联合体中的内存存储的字节数是对齐数的倍数所以可得上面的结构体在内存中所占的内存是4个字节。

枚举的定义

#include <stdio.h>

enum Sex //enum枚举类型
{
//枚举类型的可能取值
Male,
Female,
secret
};

enum RGB
//枚举类型中的值是最开始自动初始化的值从0开始往下递增1
{
Red = 8,//当把最上面的值赋值了一个数那么下面的数据的值就从这个数开始往下递增
Green,
Blue
};

int main()
{
enum Sex s = Female;//创建一个枚举类型
enum RGB rgb = Green;//创建一个颜色枚举类型
printf("%d\n", Red);
printf("%d\n", Green);
return 0;
}

上面的代码所得的结果为;

在这里插入图片描述

  1. 在枚举类型中编译器会自动将定义在枚举中的最上面的成员的值定义成0,之后下面的成员的值会从0开始依次进行+1赋值即:
    例如上面的枚举类型Sex中Male的值为0 , Female的值为1 ,secret的值为2.

  2. 在枚举类型中如果将枚举中的一个成员进行赋值,那么这个成员下面的成员就会从赋给的这个值开始依次+1赋值即
    例如上面的枚举类型RGB中将Red的值赋为8,那么Green的值为9,Blue的值为10依次赋值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值