栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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);这样一个函数可以实现算出,结构体成员再内存中的偏移量,他的头文件是,这是一个宏的概念

        

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/302597.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号