你好, 欢迎｡ 我们在一个新的部分｡
我们将讨论结构｡
这是c语言中的一个新概念,
允许你将项分组在一起, 类似于数组, 但功能更强大｡
我想谈谈什么是结构, 你如何创建和使用结构｡
因此c中的结构提供了另一种将元素组合在一起的工具｡
我再次提到, 它们类似于数组, 但实际上功能更强大.
如果你熟悉面向对象的编程, 如果你用java或c-plus plus或任何面向对象的语言编程,
它就像一个对象,
但只有数据成员, 没有实际的行为, 没有方法｡
因此, 这是一个强大的概念,
你将在你开发的许多c程序中使用, 因为你可以将不同的项组合在一个名称中, 这些项可以代表本质上的数据属性｡
比如说你想在一个程序里存储一个日期｡
日期通常由三个变量组成：月､ 日和年｡
您将创建这三个变量来存储该数据｡
例如, 你会说整数月等于9天等于25年等于2015年｡
假设您的程序还需要存储特定项目的购买日期｡
你可能需要为程序中使用的每个日期再创建三个变量｡
所以你可以看到这是如何变得非常重复的, 你最终会创造出很多变量｡
但你应该注意到这些变量在逻辑上是相关的｡ 都是约会｡
他们真的应该被归在一起｡
它们几乎应该是它们自己的数据类型, 然后您应该能够创建它们并访问不同的元素｡
您不必为每个日期创建三个单独的变量｡
所以这也是它与对象和一个有三个数据属性的类的关系｡
所以如果你能把这三个变量组合在一起, 那就更好了｡
而这正是结构元素所做的, c.
它允许您使用特定的名称将这些不同的元素分组在一起｡
然后你可以用这个名字创建不同的变量, 然后用这个名字访问元素, 不同的数据属性,
它们实际上被称为成员.
那么如何在c中创建一个结构｡
这非常非常简单｡ 结构声明描述了结构是如何组合在一起的｡
结构内部有哪些元素｡
而我们通常将这些元素称为成员｡
因为您首先必须定义结构或宣告结构, 所以请描述结构内部的内容｡
所以你可以用struct关键字来实现｡
struct保留字可让您定义称为结构的各种型别变数集合, 您可以将其视为单一单位｡
非常非常强大｡
因此, 通过使用struct关键字, 您所要做的就是提供一个名称,
这通常被称为标记名称｡ 在这个例子中, 我们有一个date标签名｡
但是你可以看到关键字struct, 它告诉c编译器,
这是一个特定的函数.
这可以具有特定的功能, 允许您对元素进行分组｡
struct是关键字, 后面跟标签名, 然后是左大括号和右大括号,
后面跟分号.
在里面, 你可以定义任何类型的变量, 你甚至可以在里面放指针｡
这些被称为结构的成员｡
所以这又是一条语句, 它定义了一个c编译器能够理解的日期结构｡
它告诉c编译器状态结构将包含什么, 三个元素：月､
日和年｡
此声明没有内存分配｡
你的意思是说这是一个存在的结构｡
我还没开始用呢｡ 我只是说这就是它的定义｡
这是日期结构, 这是它的组成部分.
日期结构中的变量名, 即月､ 日和年,
这些变量名称为成员或字段｡
结构的成员会出现在结构标记名称date之后的大括号之间, 因此标记名称date｡
非常非常简单的语法, 将这些元素组合在一个名称date中｡
你注意到它和数组不同因为它没有索引,
你实际上没有指定大小.
它不是完全相同的数据类型｡
您可以有不同的数据类型, 也可以有许多不同的数据类型｡
那么你会如何利用这个结构｡
日期的定义定义了语言中的一种新类型｡
你可以把它想象成另一种类型, 就像int, double或者float一样.
除了您定义的这个类型之外, 您几乎可以将其视为一个枚举｡
除了枚举只保存一个值｡
此日期结构可以保存三个值, 但它是另一种数据类型｡
现在可以将变量声明为struct to date类型｡
所以这正是你会做的｡
你可以创建一个新的变量today, 它的类型是struct
date.
今天我们基本上可以持有三个价值观｡
然后,
如果需要声明更多的日期, 可以创建更多相同类型的变量｡
所以你不再需要三个独立的变量来表示购买日期,
三个独立的变量来表示当前日期, 三个独立的变量来表示结算日期｡
您可以拥有该实际结构的不同实例的一个变量或两个变量｡
希望你能注意到它的强大功能｡
所以上面的语句是结构日期, 购买日期.
现在已配置内存, 因为您宣告了变数Memory is allocated for
this structure｡
内存是为三个整数值或每个变量的三个成员分配的, 因此内存将被分配｡
它被分配的原因是因为这里没有指针｡
如果该结构中有指针, 则必须为该指针分配内存｡
但是因为今天的日期结构体是非常简单的结构体,
我开始的时候比较慢, 它包含了三个整型数, 这些整型数是自动分配给你的｡
但是, 请确保您理解了上一张幻灯片和当前这张幻灯片的区别｡
定义结构和声明该特定结构类型的变量是有区别的｡
财务结构只是告诉c编译器这是一个结构,
这是它里面的数据.
但实际上声明一个特定结构类型的变量就是说我将开始使用这个结构｡
现在, 我已经为示例中的三个元素分配了内存,
并且可以访问这些元素并对其进行设置｡
那么, 如何访问结构体中的成员呢？
现在你已经知道了如何定义一个结构, 以及如何声明结构变量,
你现在需要能够理解如何引用struct的那些成员.
你必须访问它们｡ 如果您无法访问它们以查看值或设置值, 则它将毫无用处｡
所以结构变量名不是指针｡
因此, 您需要使用特殊的语法来访问成员｡
因为指针通常只包含地址的值｡
如果它不是一个指针, 那么你就需要一些特殊的语法｡
您可以在变数名称后面加上句号, 以指涉结构的成员｡
它通常被称为点操作符｡
然后在点运算符句点之后, 跟随该结构体内部的成员变量的名称｡
结构变数名称和成员名称之间的句号称为成员选择运算子, 也称为点运算子｡
变量名､ 句点和成员名之间不允许有空格｡
要将变量today中的日期值设置为25, 我只需执行以下操作｡
变量的名字是今天, 然后我会说点, 两边之间没有空格｡
然后我会在结构定义中指定元素的名称, 即day｡
然后我会像给其他整数赋值一样给它赋值｡
我会使用equals赋值运算符,
这里是一个常量, 还有分号｡
非常非常简单｡
如果我想指定年份, 我会说今天｡ 比如说2015年
以及何时要访问成员值｡
例如, 如果我想访问month的成员值, 看看它是否等于12,
我仍然会使用点语法, 即成员选择运算符｡
因此, 您可以使用成员选择运算符来访问成员值｡
当您访问这些成员变量时, 您可以像使用其他变量一样使用它们｡
如果它们是整型的, 你可以在算术运算中使用它们｡
您将遵循该数据类型的规则｡
在这个例子中, 我们可以把它和12进行比较,
只需要在if语句中使用equals｡
然后, 例如, 如果它等于12, 我们可以说下月等于1｡
这可能是一个局部变量, 我们将分配｡
让我们看一个例子｡ 这里我们定义了一个名为date的结构体｡
我们有三个元素, 整数：月､ 日和年｡
我们知道我们在定义它, 因为我们有struct关键字和那些花括号｡
然后还要注意右大括号有一个分号来结束定义｡
此时, 没有为该结构分配内存｡
在下一行中, 我们实际上声明了一个该类型的变量, 因此我们现在为一个实际上包含三个元素的变量名分配内存：int类型的月､
日和年｡
我们现在可以通过使用dot成员访问, 将数据分配给结构体中的这三个元素｡
所以今天｡ 一个月等于九, 就是今天｡ 天等于25和今天｡ 2015年｡
如果我们想打印它或访问该数据, 我们将在分配它之后以相同的方式访问它｡
我们只需使用成员选择：就在今天｡ 月, 今天｡
天, 今天｡ 一年｡ 同样, 我们可以对它进行算术运算, 因为它是一个int｡
我们可以使用percent d, 或者如果我们想将其格式化为2, 我们可以使用percent
2I或percent 2D｡
这是一个非常简单的语法, 很容易创建和定义结构, 然后使用它们,
然后使用点成员选择运算符访问它们｡
结构和表达式呢？
你刚才看到我可以访问数据, 使用算术表达式, 这没什么不同.
当涉及到表达式的求值时, 结构成员遵循与普通变量相同的规则｡
如果该结构中的成员是整数, 则可以对任何其他整数执行相同的规则｡
您可以应用加法､ 减法等等｡ 如果是字符缓冲区, 则只能执行字符缓冲区的规则｡
你能增加和减少字符缓冲区, 诸如此类的东西, 通常不能｡
所以浮点数,
双精度数, 所有不同的数据类型, 当你在表达式中使用这些成员时, 你只需要遵循同样的规则｡
这里有一个例子｡
我说今天｡ 年数除以一百加一｡
完全有效,
因为year是一个int, 与使用int类型的常规变量没有什么不同｡
您只需使用该成员选择运算符以不同的方式访问它即可｡
现在还有变种｡ 有不同的方法来定义结构｡
c语言最大的优点是它的灵活性, 它允许你以多种不同的方式定义一个结构｡
因此, 在定义结构时, 您可能会看到不同的语法｡
我给你们看的第一个例子是你们应该遵循的｡
您应该始终具有标记名, 并且应该在代码的一个位置定义结构, 然后在另一个位置声明它的变量｡
但c是这样的, 它非常灵活｡ 实际上, 您可以在同一行中定义结构和声明变量｡
您还可以定义匿名结构或无命名结构｡
所以有很多灵活性｡
在实际定义结构的同时, 将变量声明为特定结构的一部分是有效的｡
您可以将变量的名称放在底部｡ 我来教你怎么做｡
在结构定义的终止分号之前包含一个或多个变量名｡
您也可以像指派任何变数一样, 指派和初始化这些变数的值｡
让我们来看看｡
定义一个结构体的一个变体, 在定义的同时, 你可以声明一个变量｡
在本例中, 我们定义了struct date, 但也创建了一个名为today的变量｡
因为在右大括号的末尾,
分号前面是变量名, 它既创建了date结构体变量, 又定义了date结构体变量.
在上面的例子中, 你创建了一个结构变量｡
我们也将其称为结构的实例｡ 今天就叫今天｡
它是在定义结构的同时声明的｡
today是一个date类型的变量, 我们一次就完成了｡
你可以在计算完today之后, 用括号初始化这些变量, 然后说month等于5, day等于,
等等, 就像初始化其他整数一样.
现在, 你可以创建一个结构的另一种方法是你可以创建一个未命名的结构｡
这是一个更有限的, 因为你不能用它做很多事情｡
但实际上不必提供标记名｡
请记住, 标记名称位于顶部, 就在struct关键字之后｡
在前面的示例中, 标记名称为date｡
但你不必提供日期｡
如果在定义结构时定义了特定结构类型的所有变量, 则可以省略名称｡
这实际上意味着你只能使用这个结构一次, 而且只能一次｡
所以我们可以直接用struct,
int, day, int,
year, int, month来声明变量.
但是您会注意到struct关键字后面没有标记名｡
这只是一个结构｡
我们只使用一次, 所以我们今天创建了这个变量, 然后我们就再也不会使用它了｡
这就是它的缺点和局限性｡
除非你有一个局部结构体, 否则你永远不想这样做｡
但是如果你把这个结构定义为一个没有名字的结构,
一个未命名的结构, 你就不能再定义它的实例了｡
你希望你的程序的所有这种结构类型的变量都必须在一个语句中定义｡
你可以创建多个变量你可以先用today逗号然后再用另一个变量这样你就可以创建多个变量了.
您可以初始化多个变量｡
但是这种方法有一定的局限性,
因为在底部的变量声明之后, 你不能再创建任何变量｡
所以有三种方法来定义不同的结构｡
一种方法是使用标记名称定义结构, 而不创建变量｡
在分配内存时, 在单独的实例中创建变量｡
另一种方法是创建变量和结构,
同时, 你有一个标记名, 这样你就可以在程序中创建其他实例,
或者其他变量, 或者第三种方法,
你可以创建一个未命名的结构体, 没有名字, 只有底部的变量｡
同样, 你可以在创建变量的时候初始化所有这些变量, 只需要使用大括号等等｡
现在开始初始化结构｡
初始化结构与初始化数组非常相似｡
这些元素列在一对大括号内, 每个元素由逗号分隔｡
这里真的没有什么新东西要学｡
花括号内列出的初始值必须是常量表达式｡ 不能使用变量,
看起来就像数组｡
这里我们创建了一个today变量, 类型为struct date, 我们说第一个成员等于7,
第二个是2,
第三个是2015, 它对应于一年中的月日, 因为这是它们在struct中的定义顺序.
因此,
就像数组初始化一样, 列出的值可能比结构中包含的值少｡
你不需要提供全部三个,
你可以只提供两个, 这样会初始化月份和日期, 而不会初始化年份｡
所以这会设定日期｡ 一个｡
月份到12 date1｡ days设置为10, 但它不提供到目前为止的初始值｡ 一年｡
您还可以在初始化列表中指定成员名称, 这样您就不必实际具有任何顺序｡
你可以把它们放在任何你想要的顺序, 你不依赖于它｡
所以你可以这样做｡
成员等于值和结构日期, 日期为1｡ 你可以说.月等于12｡
所以它的初始语法是在大括号内设置成员, 然后赋值, dot month
equals 12, comma dot date
equals 10.
你需要那个点｡ 这个点很重要, 所以不要忘记这个点｡
点之前不需要实例｡
在下一个示例中, 我们将把date结构变量today的year成员设置为2015｡
所以这里我们只说因为记住你可以省略一些其他的成员变量｡
在这种情况下, 我们承认一天中的月份, 所以我们将把年份设置为2015年｡
在前面的例子中,
我们实际上省略了年份, 只是将月份和日期分别设置为12和10｡
我们也可以用复合文字进行赋值｡
那是一个复合词｡
您可以使用所谓的复合常值（Compound Literal）,
在单一陈述式中将一或多个值指派给结构｡
我相信这可能只在C11中｡
但今天我们有了今天, 假设我们创建了一个struct date today变量,
然后我们实际上把struct date放在括号里｡
在花括号里, 我们说的是9逗号25逗号2015｡
这是一个复合字面值｡
此语句可以出现在程序中的任何位置｡
所以与使用点成员初始化或赋值不同, 你可以在初始化完当前的结构体后,
把它放在程序的任何地方.
这不是一个声明语句｡
这是一个复合文字赋值｡
类型转换运算符用于告诉编译器表达式的类型｡
所以你需要括号里的东西, 一个类型转换, 结构日期.
值的列表跟随在转换之后, 并将按该顺序分配给结构的成员, 它依赖于顺序｡
所以它的列出方式和初始化一个结构变量的方式一样｡
同样, 这样做的好处是, 不必在单独的行上分别为每个成员变量赋值｡
您可以在一行中完成所有操作, 然后说, 这是今天变量的新值｡
您还可以使用我提到的点成员表示法来指定值｡
你只需要像这样在一行中或者在单独的行中完成它｡
这样的话, 看起来有点像初始化, 但你仍然在做复合文字｡
使用这种方法的优点是参数可以以任何顺序出现, 因此就像前面一样｡
同样, 这些赋值的关键和区别在于它不是发生在初始化过程中而是在程序的其他地方为该类型赋值.
这堂课讲了很多有用的信息｡
我们讨论了结构体, 它们的强大功能,
以及我们如何将不同的元素或变量组合成一个名称｡
我们定义结构｡ 定义结构的方法有很多种｡
然后我们还需要声明一个变量｡
一旦我们有了这个变量,
我们就可以使用点成员选择运算符访问､ 分配数据给这个结构｡
然后我们还讨论了一些不同的符号和不同的处理方式以及初始化｡
我们会用到很多结构｡
我将提出一些挑战, 帮助您熟悉此语法｡
但这仅仅是结构的开始｡
我们还必须讨论嵌套结构, 如何使用指针和结构,
以及诸如此类的东西｡
所以祝你好运, 这将是一个有趣和令人兴奋的部分｡ -谢谢—谢谢