当前课程知识点:高级语言程序设计 >  结构体和共用体 >  9.1 结构体类型的定义 >  结构体类型的定义

返回《高级语言程序设计》慕课在线视频课程列表

结构体类型的定义在线视频

结构体类型的定义

下一节:结构体类型变量和指针变量的定义和使用

返回《高级语言程序设计》慕课在线视频列表

结构体类型的定义课程教案、知识点、字幕

大家好

本讲介绍结构体类型的定义

前面几讲中

学习了一些数据类型

整型

浮点型

字符型

数组类型

指针类型

本讲学习自定义类型

在实际应用中

有不少应用问题

如果只采用上面这几种类型

显得很不方便

先来看这样一个问题

比如说

我们希望编写一个学生信息管理程序

那我们如何表示

一个学生的学号 姓名 性别等信息呢

又如何表示多个学生的信息呢

假如我们有一个班的学生信息如下表

如何将这个表格数据

用计算机存储并实现对这些数据的管理呢

到目前为止

我们唯一学习过的一种数据结构就是数组

所以自然可能会想到用数组来解决这个问题

假如这个表格中有30个学生的信息的话

一个学生的学号用一个整型变量来表示

30个学生的学号呢

就可以定义一个长度为30的整型数组来表示

姓名呢

一个学生的姓名

可以用长度为10的一维字符数组来表示

而现在要表示30个学生的姓名

那么就应该定义一个

30X10的二维字符数组

来存放30个学生的姓名

每个学生的姓名不超过10个字符

一个学生的性别

用一个字符型变量来表示

那30个学生的性别呢

就可以用一个长度为30的字符数组来表示

后面那以此类推

在定义完这些数组之后

要将这个表格中的数据

保存到这个数组元素当中去

就需要对这些数组进行初始化

我们可以在定义这些数组的同时

对这些数组进行初始化

但是用数组来存储这个表

布局是否合适呢

由于数组是具有相同类型的数据的集合

所以在保存这些学生的信息的时候

你不得不将每个学生的

学号 姓名 性别 出生年

学习成绩等等这些信息拆开来

分别用多个不同类型的数组来表示

例如所有的学号放在一个数组里

所有的姓名放在一个数组里

那现在我们要查找第1个学生的信息

在num这个数组里查到学号是403101

在name数组里查到姓名武小帝

在sex数组里查到性别等等

这是用数组保存学生信息的内存管理的示意图

有8个数组

每个数组存放学生的一个属性

这样造成分配的内存不集中

结构是零散的

查找一个学生的信息

要把所有的数组都读一遍

选址效率也不高

此外呢

易发生错位

这种内存分配方式就好比是

将多台机器设备的零部件

拆下来分开入库一样

这个时候如果你想知道哪个零部件

是哪台机器上的

可能会很难

如果每台机器都能够作为一个独立的整体

来单独存储

那就方便多了

那么有没有这样的一种数据类型

支持我们将多个逻辑相关

但类型不同的数据放在一起来存储吗

也就是将一个人的信息存放在一起

能否将不同类型的数据

放在一起定义一种新的数据类型呢

C语言允许用户自定义数据类型

典型的代表就是结构体

结构体类型和数组一样

都属于构造数据类型

它们之间的不同点就在于

数组是将相同类型的数据

放在一起来存储

而结构体允许逻辑上相关

但类型不同的数据放在一起来存储

例如在学生信息管理程序中

学生学号 姓名 性别 年龄

考试成绩等数据

都是与某一学生紧密联系的整体

那么如何来定义一个结构体类型呢

这是定义一个结构体类型的一般形式

这是针对学生数据的结构体类型

定义的具体实例

struct是C语言提供的定义结构体类型的关键字

struct后面的这个标识符student的

就是我们定义的这个结构体类型的名字

花括号里呢

是结构体类型的成员

有一个int型成员num

用来存放学生的学号

有一个长度为10的字符数组name

用来存放学生的姓名

一个字符型成员sex

用来存放学生的性别

year成员用来存放学生出生的年份

还有四个float型成员

用来存放学生的四门课的成绩

分号不能掉

表示结构体类型定义的结束

后面的四个结构体成员

我们还可以用这样的一个结构体成员来代替

就是将这四个float变量

改用一个float型数组来表示

用这种方式更具有扩展性

因为如果不是四门课的成绩

而是十门课的成绩

只要我们修改一下这个数组的长度就可以了

既可以用数组作为结构体成员的类型

也可以用结构体类型作为其成员的类型

这里year只能记录学生出生的年份

如果我们希望记录每个学生出生日期

精确到月到日

那么我们可以定义一个日期类型

日期类型有年月日三个int型成员

将学生类型的year成员的类型

修改成日期类型

将成员year的名字改为birthday

一个结构体也可以嵌套在另一个结构体内部

像这种在一个结构体内

又包含了另外一个结构体

作为其成员的结构体

我们称它为嵌套的结构体

当然这个日期类型

我们也可以这样来定义

就是将月份用一个字符型数组来表示

像 int float char 等

是由C语言本身提供的数据类型

不能再进行分拆

我们称之为基本数据类型

而结构体可以包含多个基本类型的数据

也可以包含其他的结构体

我们将它称为复杂数据类型

或构造数据类型

我们可以根据实际问题的需要来定义类型

把一组逻辑上相关的信息

作为一个整体来处理

我们知道在Visual C++中

int型占4个字节

char型占1个字节

像这样基本类型占几个字节我们都知道

现在我们自己定义的类型占几个字节呢

也就是如何计算结构体类型

占用内存的字节数呢

结构体中的成员

可以是不同的数据类型

成员按照定义时的顺序

依次存储在连续的内存空间

而数组的大小

是所有数组元素大小简单的相加

那结构体是不是和数组一样

结构体类型占内存的字节数

是不是它的所有成员

占内存字节数的总和呢

这是struct datatype1类型的定义

那么这个类型所占内存大小是1+4+1=6吗

计算类型占内存的字节数

不能想当然

而是应该用sizeof来获取

也就是用sizeof来获得一个类型

或变量所占内存的字节数

请看这个示例程序

定义了三个结构体类型

这是类型datatype1的三个成员

成员a是整型

成员b和c都是字符型

类型datatype2和类型datatype3

也各有三个成员

用sizeof来计算这三个类型所占字节数

编写这样的一个程序来计算

来看运行结果

三个类型占用内存的字节数都不相同

struct datatype1

和struct datatype3的成员类型相同

只是定义的顺序不同

struct datatype1 占12个字节

而struct datatype3占8个字节

再来看struct datatype2占6个字节数

根据运行结果

可以发现

结构体的大小不是所有成员大小简单的相加

那么是为什么呢

系统在存储结构体变量时

有一个地址对齐问题

结构体内存地址对齐是指

元素是按照定义顺序

一个一个放到内存中去的

但并不是紧密排列的

从结构体存储的首地址开始

每个元素放置在内存中时

它都会认为内存

是按照自己的大小来划分的

因此元素放置的位置

一定会在自己宽度的整数倍上开始

例如struct datatype1类型

为了与第二个基本整型的成员变量a对齐

第一个成员b和最后一个成员c

就需要在其后面添加三个字节的补位

这样就会使得这个结构体类型

实际所占内存的字节数是12

struct datatype2类型

跟struct datatype1相比

这个结构体类型的第二个成员的数据类型

是短整型

只占2个字节

那么这个结构体类型在内存中

占据的字节数就变成6个字节了

这是因为为了与第二个short型成员

变量a的内存地址对齐

第一个成员和最后一个成员的后面

只需要添加一个字节的补位

就可以实现与第二个成员的内存地址对齐了

因此这个结构体类型

在内存中占据的是6个字节的存储单元

再来看struct datatype3类型

跟struct datatype1相比

第一个成员和第二个成员都是char型

第三个成员是int型

第一个成员和第二个成员连续存放

并且在后面添加两个字节的补位

就可以与第三个int型的成员变量a

进行内存地址对齐了

因此struct datatype3这个结构体类型

在内存中占的字节数是8个字节

所以结构体类型在内存中

所占的字节数

不仅与结构体成员的数量及类型有关的

并且还与结构体成员的定义顺序相关

实际上

所有数据类型在内存中

都是从偶数地址开始存放的

且结构所占的实际空间

一般是按照机器字长对齐的

不同的编译器 平台

内存对齐方式会有变化

一个结构体在内存中的存储格式

也是与机器有关的

在使用结构体类型的时候

我们不需要关注这个细节

我们编程者无需了解

计算机内部的这种存放形式

能使用sizeof()运算符

计算结构体类型所占内存的字节数

就可以了

c语言提供了一种方法

就是用typedef

给已有的类型

定义一个新的名字

或者称为别名

例如我们可以定义给float类型

定义一个新的名字REAL

注意没有定义一种新的数据类型

而是给float类型取了一个别名

别名通常用全部大写字母的英文单词来表示

这两条语句功能相同

都是定义了两个float型变量

注意要强调的是

typedef 没有创造新数据类型

typedef 只是定义类型的别名

既不是定义新类型

也不是定义变量

typedef 还可以定义数组类型的别名

请看这是给一个长度为100的int型数组

取了一个别名ARRAY

第1条语句

是我们以前定义数组时经常用的格式

在定义了别名以后

我们定义长度为100的整型数组时

可以按第3条语句的格式写

右边呢

这是给指向char的指针类型

定义了一个别名STRING

第1条语句是我们以前定义指针变量p

和指针数组s时经常用的格式

在定义了别名以后

可以按第3条语句格式定义

指针变量p和指针数组s

再来看

typedef 还可以给结构体类型取别名

有两种方式

一是分两步

先定义结构体类型

再给这个类型取别名

第二种方式呢

可以在定义结构体类型的同时取别名

大写DATE与struct date是同义词

这两条语句是等价的

小结一下

本讲学习了结构体类型的定义

结构体中的成员可以是不同的数据类型

成员按照定义时的顺序

依次存储在连续的内存空间

结构体类型和基本类型的功能是一致的

只是告诉编译器该如何表示数据

但是它没有让计算机为它分配空间

如果我们要使用结构体变量存储数据

那么就需要先定义变量 后使用

好了 这就是我们这一讲的内容

谢谢大家

高级语言程序设计课程列表:

程序设计和C语言

-1.1 计算机程序和计算机语言

--计算机程序和计算机语言

--致敬先辈:伟大的C语言之父——丹尼斯·里奇 程序员

-1.2 C程序的构成

--C程序的构成

--当前主流程序设计语言各自都有什么优势?

-1.3 C语言编辑、编译、运行(VC++2010学习版)

--C语言编辑、编译、运行(VC++2010学习版)

-练习题

顺序结构程序设计

-2.1 变量的定义和使用

--变量的定义和使用

-2.2 数据类型

--数据类型简介

--整型数据

--实型数据

-2.3 格式输出和格式输入

--格式输出printf函数

--格式输入scanf函数

--单个字符的输入输出

-2.4 运算符和表达式

--运算符和表达式

-2.5 结构化程序设计入门

--结构化程序设计入门

-练习题

选择结构程序设计

-3.1 为什么要用选择结构解决问题

--为什么要用选择结构解决问题

-3.2 如何正确表示选择结构中的条件

--如何正确表示选择结构中的条件

-3.3 用if语句及if语句嵌套实现选择结构

--用if语句及if语句嵌套实现选择结构

-3.4 用switch语句实现选择结构

--用switch语句实现选择结构

-练习

循环结构程序设计

-4.1 循环的引入

-- 为什么要用循环结构解决问题

-4.1 循环的引入--作业

-4.2 用while语句实现循环

--用while语句实现循环

-4.3 用do-while语句实现循环

-- 用do-while语句实现循环

-4.4 用for语句实现循环

-- 用for语句实现循环

-4.4 用for语句实现循环--作业

-4.5 何时需要用循环的嵌套

--何时需要用循环的嵌套

-4.6 如何提前终止循环和提前结束本次循环

--如何提前终止循环和提前结束本次循环

-习题--作业

数组

-5.1 数组类型的引入

--数组类型的引入

-5.2 一维数组的定义和初始化

--一维数组的定义和初始化

-5.3 一维数组的使用

--一维数组的使用

-5.4 二维数组的定义和初始化

--二维数组的定义和初始化

-5.5 二维数组的使用

--二维数组的使用

-习题--作业

指针

-6.1 什么是指针

--什么是指针

-6.2 指针类型及相关概念

--指针类型及相关概念

-6.3 指针变量的定义、赋值与使用

--指针变量的定义、赋值与使用

-6.4 指针的运算

--指针的运算

-6.5 指针与一维数组

--指针与一维数组

-6.6 指针的指针

--指针的指针

-6.7 指针与二维数组

--指针与二维数组

-习题--作业

函数

-7.1 为什么要自定义函数

--为什么要自定义函数

-7.2 函数的定义

--函数的定义

-7.3 函数的调用

--函数的调用

-7.4 函数参数的传递

--函数参数的传递

-7.5 函数的嵌套调用和递归调用

--函数的嵌套调用和递归调用

-7.6 变量的作用域和存储类型

--变量的作用域和存储类型

-习题--作业

字符串

-8.1 字符串的存储及输入输出

--字符串的存储及输入输出

-8.2 系统字符串处理函数

--系统字符串处理函数

-8.3 自定义字符串处理函数

--自定义字符串处理函数

-习题--作业

结构体和共用体

-9.1 结构体类型的定义

--结构体类型的定义

-9.2 结构体变量及指针变量的定义及使用

--结构体类型变量和指针变量的定义和使用

-9.3 结构体变量和指针变量作函数的参数

--用结构体变量和指向结构体的指针作函数参数

-9.4 结构体数组的定义和使用

--结构体数组的定义和使用

-9.5 共用体类型和枚举类型

--共用体和枚举类型

-习题--作业

动态内存分配

-动态内存分配--习题

文件

-习题--作业

结构体类型的定义笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。