结构中的结构
别忘了,定义结构其实就是在创造新的数据类型。C 语言有很多内置数据类型,例如
int 和 short ,但有了结构,我们就可以把现有类型组合起来,向计算机描述更复杂的东西。
既然结构可以用现有数据类型创建数据类型,也就能用其他结构创建结构。具体怎么做?来看一个例子。
上述代码向计算机描述了一个结构中的结构。你可以像之前一样用数组语法创建变量,但现在可以在数据中包含结构中的结构。
一旦把结构组合起来,就可以使用一连串的“.”运算符来访问字段:printf("Snappy 喜欢吃 %s", snappy.care.food);printf(
"Snappy 喜欢锻炼 %f hours", snappy.care.exercise_hours);
快试试你的新技能吧……为什么要嵌套定义结构?之所以要这么做是为了对抗复杂性。通过使用结构,我们可以建立更大的数据块。通过把结构组合在一起,我们可以创建更大的数据结构。本来你只能用 int 、short ,但有了结构以后,就可以描述十分复杂的东西,比如网络流和视频图像。
练习
Head First 水族馆的人开始登记鱼的信息,每条鱼都有很多数据要记录,这是它们的结构:struct exercise { const char *description; float duration;}; struct meal { const char *ingredients; float weight;}; struct preferences { struct meal food; struct exercise exercise;}; struct fish { const char *name; const char *species; int teeth; int age; struct preferences care;};
其中某条鱼有以下数据要记录:Name: SnappySpecies: PiranhaFood ingredients: meatFood weight: 0.2 lbsExercise description: swim in the jacuzziExercise duration 7.5 hours
问题 0:这条数据用 C 语言怎么表示?问题 1:补全 label() 函数的代码,输出以下信息:
练习解答
Head First 水族馆的人开始登记鱼的信息,每条鱼都有很多数据要记录,这是它们的结构:struct exercise { const char *description; float duration;}; struct meal { const char *ingredients; float weight;}; struct preferences { struct meal food; struct exercise exercise;}; struct fish { const char *name; const char *species; int teeth; int age; struct preferences care;};
其中某条鱼有以下数据要记录:Name: SnappySpecies: PiranhaFood ingredients: meatFood weight: 0.2 lbsExercise description: swim in the jacuzziExercise duration 7.5 hours
问题 0:这条数据用 C 语言怎么表示?问题 1:补全 label() 函数的代码,输出以下信息:
用 typedef 为结构命名。
当创建内置数据类型变量时,只要写 int 或 double 就行了,但每次创建结构变量时,不得不加上 struct 关键字。 struct cell_phone { int cell_no; const char *wallpaper; float minutes_of_charge; };... struct cell_phone p = {5557879, "sinatra.png", 1.35};
在 C 语言中可以为结构创建别名,你只要在 struct 关键字前加上 typedef ,并在右花括号后写上类型名,就可以在任何地方使用这种新类型。
typedef 可以用来缩短代码长度,并让代码更容易阅读。试试在代码中加入 typedef ……新类型叫什么?当你用 typedef 为结构创建别名,需要决定别名叫什么。别名其实就是类型名,也就是说结构有两个名字:一个是结构名(struct cell_phone ),另一个是类型名(phone )。为什么要有两个名字?一般一个就够了。如果只写类型名而不写结构名,编译器也没意见:
练习
潜水员要开始巡逻水池,他需要给潜水服贴上新的标签。问题是一些代码不见了,你能写出来吗?
练习解答
潜水员要开始巡逻水池,他需要给潜水服贴上新的标签。问题是一些代码不见了,你写出来了吗?
要点
结构是一种由一系列其他数据类型组成的数据类型。
结构的大小固定。
结构字段按名访问,用<结构>.<字段名>语法(也叫“点表示法”)。
结构字段在存储器中保存的顺序和它们出现在代码中的顺序相同。
可以嵌套定义结构。
typedef 创建数据类型的别名。
用 typedef 定义结构时可以省略结构名。
这里没有蠢问题问:结构字段在存储器中是紧挨着摆放的吗?答:有时两个字段之间会有小的空隙。问:为什么?答:计算机总是希望数据能对齐字边界(word boundary)。如果计算机的字长是 32 位,就不希望某个变量(比如 short)跨越 32 位的边界保存。问:所以计算机会留下一道空隙,然后在下一个 32 位字开始的地方保存 short ?答:是的。问:也就是说,每个字段都占用一整个字?答:不一定,计算机在两个字段之间留出空隙仅仅是为了防止某个字段跨越字边界。如果几个字段能放在一个字中,计算机就会那么做。问:为什么计算机如此在意字边界?答:计算机按字从存储器中读取数据,如果某个字段跨越了多个字,CPU 就必须读取多个存储器单元,并以某种方式把读到的值合并起来。问:这样会很慢吗?答:会很慢。问:在 Java 那样的语言中,如果我把对象赋给变量,它不会复制对象,仅仅复制引用,为什么 C 语言不这样做?答:在 C 语言中,所有赋值都会复制数据,如果你想复制数据的引用,就应该赋指针。问:结构名的问题我还没搞清楚,什么是结构名?什么是别名?答:结构名是 struct 关键字后 面的那个单词。假设你写的是 struct peter_parker{ ... } ,那么结构名就是 peter_parker ,当创建变量时,你会写 struct peter_parker x 。问:那别名呢?答:有时,你不想在声明变量时还使用 struct 关键字,那么就可以用 typedef 创建别名。typedef struct peter_parker { ... } spider_man; 里面的 spider_man 就是别名。问:什么是匿名结构?答:匿名结构就是没有名字的结构,typedef struct { ... } spider_man; 有一个叫 spider_man 的别名,但没有结构名。很多时候,如果创建了别名,也就不需要结构名了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论