C语言学习之路————结构体1.0

本文详细介绍了C语言中的结构体,包括结构体的基础知识、声明方式、自引用、初始化以及内存对齐规则。讲解了如何声明匿名结构体、结构体变量初始化,并探讨了内存对齐的重要性及计算结构体大小的方法。同时,提到了如何通过#pragma指令修改默认对齐数,并介绍了offsetof函数的作用。
摘要由CSDN通过智能技术生成

1.结构体的基本知识

结构是一些值的集合,这些值被称为成员变量,结构体的每个成员可以是不同类型的

2.结构体的声明

  struct tag(标签,也叫结构体名)--->此出没tag叫匿名结构体类型,要注意的是,匿名结构体要及时在结构体类型后定义变量

{

    //member list(成员列)

exp:char a;

         char str[];

};//variable list(变量列)exp:s1,s2;// 首先要提到的是这个锋号,如果没有要定义的变量,要在}后面添加锋号;而定义在结构体后面的变量一般是全局变量,如果是

int main()

{

struct tag s3;

return 0;

}//这样的变量称它为局部结构体变量(s3)

匿名结构体类型要注意的是当创建一个匿名结构体之后,再以相同的成员作为结构体类型定义一个结构体类型指针,是不可行的,在编译器中会认为他们是不同的的结构体类型,即使他们的结构体成员一样

exp:

struct

{

char a;

char str[];

}s1;

struct

{

char a;

char str[];

}* ps1;

int main()

{

struct tag *ps1=&s1;//wraning

return 0;

}//值得注意的是这个没命名的结构体类型,只对他开始定义过的变量有效,也仅限在这,别的地方无法定义新的变量

3.结构体自引用

在结构体类型成员中有个结构体

这时我们要注意,直接将结构体类型对应变量,写入是不对的,我们要指向这个结构体的指针放入,

结构体中经常会使用typedef将结构体类型名,改成其他的简单的名字exp:

typedef stuct (tag){

tags* next//error

struct tag* next;//right 

}tags;如果没有tag,是个匿名结构体类型这里的成员列里不能出现结构体的自引用,

在为改名之前就自应用,程序不会识别这个新的类型名

4.结构体变量初始化

struct body{

double weight;

int height;

}t;

struct stu{

char name[];

struct body t;

short age;

}p;

int main()

{

struct stu p={“wangming”,{60.0,175},23};

struct stu* pp=&p;

printf("%s",p.name);//点这个字符是用来访问结构体成员的,

printf("%s",pp->name)//这个是指针访问结构体成员的

return0;

}

5.结构体内存对齐(求结构体的大小)

规则;第一个成员在于结构体变量偏移量为零的地址处//偏移量是指在结构体在内存中放置的第一个位置空间(偏移量为0)算起,每向下一个字节,偏移量加1,

        其他成员要对齐某个数字(对齐数)的整数倍的地址处(对齐数:编译器中默认的对齐数和成员大小的较小值)注意字符型数组或者数字型数组的对齐数为元素所占空间大小

        结构体的大小为最大对齐数的整数倍

        如果结构体内嵌套结构体,还是先算出这该嵌套结构体的大小,在与默认对齐数比较

exp:

struct stu

{

char a;//sizeof=1对齐数为1

char a1;//sizeof=1对齐数为1

int b;//sizeof=4对齐数为4    ,前面的两个char相继占据了偏移量为1和0的两块空间(任何数都是一的倍数)而第三个成员要放在对齐数的倍数处,也就是偏移量为对齐数的倍数处,偏移量为四的位置刚好是第三个成员对齐数4的倍数,就在这里开始存放第三个成员(在第二个成员地基础上向后偏移了两字节,而这跳过的两字节空间将会被浪费掉)4+4=8,8也正好是最大对齐数4的倍数,所以该结构体的大小为8

}s1;//vs里的默认对齐数为8

int main()

{

  printf("%d",sizeof(s1));//8

  return 0;

}

我们在放置成员的时候,讲究是将小的数据集中放置,可以减少空间的浪费

注意:在gcc环境下,没有默认对齐数

结构体内存对齐的原因:1.不是所有硬件平台都能访问任意地址上的任意数据的,只能在某些地址的取特定数据,2.内存对齐可以减少访问一个数据的次数即减少运算时间,exp:char a;int b;如果不按照内存对齐来存储,这个结构体会在内存中站5个字节,而在32位机器上每次读取4个字节,而b就会分两次读取,而内存对齐后这里的结构体大为8,a存完后会浪费三个字节的空间,再存储b,先一次读a,再一次都b,总共才需要两次,很好的节省了时间,说白了,内存对齐是用空间来换取时间

6.修改默认对齐数

我们可以用#pragma这个预处理命令,改变默认对齐数

#pragma pack(size_t为要设置的默认对齐数数字,而什么都不给,就是取消默认对齐数)

这里涉及到的size_toffsetof(structName,memberName);这样一个函数可以实现算出,结构体成员再内存中的偏移量,他的头文件是<stddef.h>,这是一个宏的概念

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值