结构体类型、联合体类型
结构体和联合体
- 一、结构体类型
- 1. 结构体类型的设计和初始化
- 2. 结构体大小的计算
- 3. 结构体成员的访问和赋值
- 4. 结构体类型和指针
- (1)变量名为指针时:
- (2)结构体赋值时容易出现的问题:
- (3)结构体成员为指针时
- 二、联合体类型
- 1. 联合体的三种定义方式
- 2. 联合体的内存分配
- 3. 结构体嵌套联合体的内存大小的计算
- 4. 联合体的使用
一、结构体类型
设计结构体类型是为了把各个类型不同的相互有联系的变量放在一起,反应他们的内在联系。
1. 结构体类型的设计和初始化
下面将定义一个学生结构体:
struct Student //struct是结构体类型的关键字,Student为类型名
{int num; //学号为整型char name[20]; //姓名为字符串char sex; //性别为字符型int age; //年龄为整型float score; //成绩为实型
}; //结构体在设计时花括号后面必须有分号int main ()
{struct Student s1={“1001”,”hyy”,”m”,23,105.5};//在给结构体初始化时,必须注意要按照顺序赋值,不能将顺序打乱;
}
注意:
- 结构体之间可以嵌套:例如学生由姓名、性别、生日构成,生日由年、月、日构成。其中嵌套的结构体可以用花括号括起来,也可以不用。
- 结构体是一种数据类型,不能存放数据,不占用空间,结构体变量能存放数据需要储存空间。
- 结构体成员在内存中的储存情况也是按顺序的。
2. 结构体大小的计算
由于存储变量地址对齐的问题,计算结构体大小的3条规则:
- 结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍。
- 结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
- 结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节数"的整数倍。
比如计算上述结构体大小:16字节
struct node
{char cha;char chb;int a; //大小为8字节
}struct node
{char cha;double chb;int a; //大小为24字节
}
嵌套结构体的计算:
struct sdate
{int year;int month;int day;};
struct Student
{char s_id[10];char s_name[8];struct sdate birthday;//嵌套结构体double grade; //32字节
};
3. 结构体成员的访问和赋值
结构体变量的成员使用.访问。访问和赋值的一般格式为:结构体变量名.成员名。
struct Student
{int num; char name[20]; char sex; int age; float score;
};
int main ()
{struct Student s1;s1.num=1010101; s1.age=18; //结构体变量名.成员名型式
}
注意:
- 结构体类型相同的变量可以作为整体相互赋值。在其他情况的使用过程中只能对成员逐─赋值。
- 如果结构体成员是数组时,结构体变量之间是不能相互赋值或初始化的,因为数组之间不能相互赋值,如果要赋值必须要调用字符串的拷贝函数。
- 在c语言中不存在对结构体类型的强制转换(和内置类型的区别),即标识符不同不能进行相互赋值。
4. 结构体类型和指针
(1)变量名为指针时:
内置类型能够定义指针变量,结构体类型也可以定义结构体类型的指针
结构体类型指针访问成员的获取和赋值形式:
(p).成员名(.的优先级高于,(*p)两边的括号不能少) 或 p->成员名
struct Student
{int num; char name[20];
};
int main()
{struct Student s2={10101,"gaoqia"};struct Student *s3=&s2(*s3).num=123456; //指针指向成员赋值s3->num=123456; //指针访问成员
}
分析下面两种打印函数,那种比较好?
答案:第二种较好,因为使用指针形式可以节省空内存间
(2)结构体赋值时容易出现的问题:
#include<stdio.h>
struct School
{char s_name[20]; int s_age;
};
void Init_School(struct School* sp) //这里必须使用传地址的方式,传值方式不改变实参的值。
{scanf_s("%s", sp->s_name, 20); //使用指针指向赋值对象scanf_s("%d", &sp->s_age); //赋初值时,普通变量需要取地址符,数组不用
}
void Print_School(struct School *sp) //直接传递结构体效率太低所以用指针的方式传递
{printf("name:%s\n", sp->s_name); printf("age: %d\n", sp->s_age); //将sp的地址指向对象
}
int main()
{struct School s1 = {};Init_School(&s1); //使用传地址方式。Print_School(&s1);return 0;
}
如果将s_name定义成数组型式,各处变化如下:
#include<stdio.h>
struct School
{char* s_name; int s_age;
};
void Init_School(struct School* sp)
{static char name[20]; //定义数组name,让s_name指向name,即开辟空间。sp->s_name = name; //这里必须使用静态关键字,不然会有失效指针出现。scanf_s("%s", sp->s_name, 20); scanf_s("%d", &sp->s_age);
}
void Print_School(struct School *sp)
{printf("name:%s\n", sp->s_name); //原本sp->s_name指向的是一个空指针不能存放数据,除非s_name指向一块空间printf("age: %d\n", sp->s_age);
}
int main()
{struct School s1 = {};Init_School(&s1); Print_School(&s1);return 0;
}
在结构体指针成员赋值时,指针成员应该指向一个空间,在函数中定义一个数组让指针指向之后,函数调用结束,系统分派的栈帧空间被释放,指针失效,打印的是乱码,所以应该用静态关键字。
(3)结构体成员为指针时
当结构体成员的类型为指针类型时,储存的方式和其他类型有所不同,栈帧中为指针开辟空间,指针所指向的字符串存在.date区,也是只读区,由指针指向而已。如下图:
两者对比:
如图1所示的结构体,在主函数中定义结构体也是不能编译通过的,因为结构体虽然可以嵌套,但是这样无穷的嵌套不允许有,执行时会发生溢出.
如果将studx,定义为*studx就可以,因为指针不是实实在在的学生结构体变量,它只占了四字节。
二、联合体类型
联合体:对同一内存空间采取不同类型进行解释,联合体变量的长度时成员最长的长度,联合体变量赋值时,新的值会冲掉旧的值。
1. 联合体的三种定义方式
关键字:union
2. 联合体的内存分配
两种方式占用内存的方式不同如下图:
联合体的大小:是联合体内最长字节成员变量的字节数
3. 结构体嵌套联合体的内存大小的计算
4. 联合体的使用
**点分十进制:**我们的ip地址就是联合体类型的
点分十进制的具体实现:
union IPNode
{unsigned int addr;strust{unsigned char s4;unsigned char s3;unsigned char s2;unsigned char s1;};
};
void uint_to_ipstr(unsigned int ip ,char*buff)
{if(buff==nullptr)return ;IPNode x={};x.addr=ip;printf("%d.%d.%d.%d\n",x.s1,x.s2,x.s3,x.s4);
printf输出函数是将数据格式化之后打印到屏幕上
Sprintf函数是将数据格式化之后缓存到缓冲区buff中,sprintf_s(buff,300,”%d”,a)
结构体类型、联合体类型相关推荐
- c语言枚举和结构体的区别,全面了解结构体、联合体和枚举类型
一. 结构体: 1. 定义结构体类型: struct 结构体 { 任意类型 任意变量: 任意类型 任意变量: -- }: 注意:这不是定义变量,而是自定义一种类型而已. 如 struct studen ...
- 结构体,枚举类型与联合体
目录 编辑 一.结构体的基本使用 1.什么是结构体 2.结构体的一般声明 3.结构体的特殊声明 4.结构体的自引用 5.结构体变量的定义和初始化 二.结构体内存对齐 1.内存对齐规则 3.为什么会存 ...
- C#语言基础——结构体和枚举类型
结构体和枚举类型 一.结构体(struct) 结构类型是用户自己定义的一种类型,它是由其他类型组合而成的,可包含构造函数.常数.字段.方法.属性.索引器.运算符.事件和嵌套类型的值类型.结构在几个重要 ...
- c语言 typeof 结构体,Go语言通过反射获取结构体的成员类型
任意值通过 reflect.TypeOf() 获得反射对象信息后,如果它的类型是结构体,可以通过反射值对象(reflect.Type)的 NumField() 和 Field() 方法获得结构体成员的 ...
- c++ 结构体中不同类型的初始值_Golang语言基础教程:结构体
1.1 什么是结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型.结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 1.2 结构体的定义和初始化 ...
- python中的记录指针_使用Python向C语言的链接库传递数组、结构体、指针类型的数据...
使用python向C语言的链接库传递数组.结构体.指针类型的数据 由于最近的项目频繁使用python调用同事的C语言代码,在调用过程中踩了很多坑,一点一点写出来供大家参考,我们仍然是使用ctypes来 ...
- python结构体数组传出接收c动态库_使用Python向C语言的链接库传递数组、结构体、指针类型的数据...
使用python向C语言的链接库传递数组.结构体.指针类型的数据 由于最近的项目频繁使用python调用同事的C语言代码,在调用过程中踩了很多坑,一点一点写出来供大家参考,我们仍然是使用ctypes来 ...
- SV学习笔记—结构体及枚举类型及字符串
目录 1.结构体 1.1 压缩结构体 1.2 非压缩结构体 1.3联合结构体 2.枚举类型 3.字符串 1.结构体 Verilog的最大缺陷之一是没有数据结构,SV中可以使用struct语句创建结构, ...
- C语言结构体与联合体
c语言结构体与联合体 结构类型定义和结构变量说明 一.结构的定义 二.结构类型变量的说明 结构变量的赋值 结构变量的初始化 结构数组 结构指针变量 其访问的一般形式为: (*结构指针变量).成员名 结 ...
- 自己实现了一个C语言例程,加深对宏、大小端、typeof宏、offsetof宏、指针变量、结构体、联合体的理解
如题所述,最近时间在复习C语言.自己实现了一个C语言例程,以加深对宏.大小端.typeof宏.offsetof宏.指针变量.结构体.联合体的理解.关于细分知识后续有空再填充- swap宏的使用: 对应 ...
最新文章
- php 格式化评论量函数,深入剖析PHP中printf()函数格式化使用
- WEEX 报错 TypeError: Converting circular structor to JSON 的解决方法
- 使用 Oracle GoldenGate 进行实时数据集成
- OpenGL 开发环境配置(Windows) - Visual Studio 2017 + GLFW + GLAD 详细图文教程
- b350主板支持cpu列表_惊!AMD旧主板通过这个方法竟也能支持PCIe4.0
- php开源问答_PHP基础知识能力问答
- 唯有自己变得强大_物竞天择,适者生存,唯有强大自己,方能百毒不侵
- Re: 社团改革还让不让人活了?
- iOS 项目开发工具JIRA
- 字体感觉小了 引入的vant_动态字体海报如何设计与制作?
- 线上售楼处,卖房神器还是营销噱头?
- 求向量的垂线_高考数学填空题如何快速求直线关于直线对称的直线方程
- win7蓝屏0x0000003b解决教程
- 计算机教师继续教育心得,教师继续教育个人总结(通用5篇)
- 仪器仪表课程上的大作业——示波器的使用
- 【虹科讲座预告】企业如何防止基于USB的数据外泄
- mcinabox运行库下载_mcinabox启动器下载直装版-mcinabox运行库下载v1.1.3 安卓版-2265手游网...
- 计算机网络-----TCP三次握手相关面试题扩展
- 使用连接管理器出现“安装程序无法复制文件”错误的解决方法
- 【机器学习实战】KNN
热门文章
- nginx大量TIME_WAIT的解决办法(转载)
- leetCode 46. Permutations 回溯问题 | Medium
- 每天学一点Scala之 伴生类和伴生对象
- JZOJ.5234【NOIP2017模拟8.7】外星人的路径
- Javascript模块化编程(三):require.js的用法
- jQuery Callbacks
- DNS Serv管理与维护
- 安全攻防技能——安全基础概念
- 某程序员感叹:本是家族边缘人,但亲戚得知自己年入二百万后,都上来巴结!...
- 文件 IO 中如何保证掉电不丢失数据?