自定义类型理解

文章讲述了C语言中结构体的概念,用于组合不同类型的数据。结构体可以被typedef重命名,也可以创建匿名结构体。文中还讨论了结构体的自引用情况,以及结构体变量的定义和初始化。特别地,文章重点解释了内存对齐的规则,举例说明了如何计算结构体的大小,并指出内存对齐对于不同硬件平台的兼容性重要性。
摘要由CSDN通过智能技术生成

我们生活中有许多数据我们可以用整型,浮点型来描述,但是如果有一天我们要描述一本书,描述它的售价,书名,页数等信息我们是无法用整型去描述的,这个时候c语言提供了结构体,结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同的变量,所以如果我们需要描述一本书,我们就可以把它的售价,书名,页数作为一个集合定义一本书

一结构体的声明

struct stu
	{
        char name[20];名字
		int a;年龄
	};

1如果要将类型重命名,有两种方法,

(1)

typedef struct Stu
	{
        char name[20];名字
		int a;年龄
	}stu;
将struct stu重命名为stu

(2)

struct Stu
	{
        char name[20];名字
		int a;年龄
	};
typedef struct Stu stu

2  特殊的声明(这种声明的结构体又称为匿名结构体)

struct   省略了标签名
	{
		int a;
		char b;
		float c;
	}x;   正是因为未写标签名,导致定义变量只能在声明结构体的时候定义,不然写两个这样的
          结构体,然后在程序任意处定义变量,编译器怎么知道这个变量是哪个类型
struct   
	{
		int a;    
		char b;   
		float c;
	}*p;

如果此时我们又定义一个匿名结构体,而且和第一个结构体的成员变量类型一样
p=&x;
你觉得指针变量p的类型和x的类型是一样的吗?

虽然两个结构体成员变量类型一样,但是编译器仍认为两个结构体是不同的类型,c语言对于上述类型不匹配未有警告,但是在c++该代码会报错。

3  结构体的自引用

//代码1
struct Node
{
int data;
struct Node next;
};

如果这种类型可以,那sizeof(structNode)的值是无限大的,就像是一个无限嵌套的递归
//代码2
struct Node
{
int data;
struct Node*next;//指针大小是已经知道的,所以我们这个结构体大小是可知的
                 //具体用法貌似和数据结构有点相关,目前还未涉及,所以我对这个自引用的理解不深
};

4 结构体变量的定义和初始化

   结构体终究是一种类型,要想存储信息只有用这种类型定义一个变量,才会在内存开辟空间,之后就是初始化的问题了,我们只要把结构体成员变量都初始化完就等价于把结构体初始化了。

struct Point
{
 int x;
 int y;
}p1;//声明类型的同时定义变量p1

struct Point p2;//定义结构体变量p2

//初始化:定义变量的同时赋初值。
struct Point p3={x,y};

struct Stu
//类型声明
{
 char name[15];//名字
 int age;//年龄
};
struct Stu s={"zhangsan",20};//初始化

struct Node
{
  int data;
  struct Point p;
  struct Node*next;
}n1={10,{4,5},NULL};//结构体嵌套初始化

structNoden2={20,{5,6},NULL};//结构体嵌套初始化

5 结构体内存对齐(计算结构体的大小)

struct S1
	{
		char c1;
		int i;
		char c2;
	};
	printf("%d", sizeof(struct S1));

要计算上面那个结构体的大小时,我们可能会认为结构体大小就是结构体成员大小之和,那结果可能是6字节,但当我们运行起来后可以发现,结果为十二,这说明计算结构体大小的规则并非如此。

所有结果都是规则导致的。

结构体对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到偏移量是自己对齐数的整数倍的地址处。
(对齐数=编译器默认的一个对齐数与该成员大小的较小值)。
VS中默认的值为8

3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

所以分析上述结构体大小,实际内存占用是如下图的

根据规则1第一个成员在偏移量为零处开始占用,所以不管第一个结构体成员是什么类型变量,都从0处开始占用内存而其它的成员变量使用内存的位置则看规则2,int类型的对齐数是4,所以要放在偏移量是4(偏移是相对结构体变量的地址,这一点要分清楚,所以嵌套结构体放任意位置占用大小不变)的整数倍上,往后占用4个字节,第三个成员变量是字符类型,大小为一个字节,任何整数都是1的倍数,所以第三个结构体成员紧跟着放在偏移量为8的位置上,此时我们从图片可以看到1到3的内存未被占用,但还是算入大小之中,此时结构体已经使用了9个字节,最后要看规则3,结构体总大小是最大对齐数(本例题中最大为4)的整数倍,所以我们要把9到11(也就是橙色区域)也划入结构体,故结果为十二字节大小。

struct S4
	{
		char c1;
		struct S1 s1;
	};
	printf("%d\n", sizeof(struct S4));

这个结构体内部还嵌套了个结构体,此时s1要存储的位置的偏移量应该是结构体S1最大对齐数的整数倍,也就是4的整数倍处,而这个s1的大小我们已经算出是12字节,所以综合起前面的0到3的空间,共占用16字节。

注:数组的对齐数看数组元素的对齐数

为什么存在内存对齐?
大部分的参考资料都是如是说的:
1.平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特
定类型的数据,否则抛出硬件异常。(这些估计我要到实际工作中才好理解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小何只露尖尖角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值