C学习笔记
——结构
结构是 一个或 多个变量的集合。这些变量可以是不同的类型。
一、结构入门
<span style="color:#cc66cc;"><strong>struct 结构标记 { <span style="white-space:pre"> </span>成员; } 变量表;</strong></span>
结构标记是 可选的,用于为结构命名。在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式。变量表也是 可选的。 如果结构声明的后面不带变量表,则不需要为他分配存储空间,仅仅描述了一个结构的模板或轮廓。
- 结构表量的声明
结构标记与变量表均存在;既可以先声明一些需要的变量,也可以在后续过程中使用 struct 结构标记来声明变量。
<span style="color:#cc66cc;"><strong>struct结构标记</strong></span> <span style="color:#cc66cc;"><strong>{<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>成员; } 变量表;</strong></span>
结构标记省略;因为没有结构标记,后续声明过程中不能使用 struct 结构标记的简化格式声明变量。
<span style="color:#cc66cc;"><strong>struct { <span style="white-space:pre"> </span>成员; } 变量表;</strong></span>
变量表省略;同第一种,只是描述结构体时不同时声明变量。<span style="color:#cc66cc;"><strong>struct结构标记 { <span style="white-space:pre"> </span>成员; } </strong></span><pre name="code" class="cpp">struct<span style="white-space:pre"> </span>结构标记<span style="white-space:pre"> </span>表量表;
- 结构体成员的引用“.”
结构名即所声明的表量名。<strong><span style="color:#cc33cc;">结构名 . 成员</span></strong>
例: struct<span style="white-space:pre"> </span>point { <span style="white-space:pre"> </span>int x; <span style="white-space:pre"> </span>int y; } struct<span style="white-space:pre"> </span>point<span style="white-space:pre"> </span>A; A即结构名。 对成员x的引用为: <span style="white-space:pre"> </span><strong>A . x </strong>
成员的初值必须是 常量表达式。结构成员、结构标记、普通变量可以采用相同的名字,不会冲突。不同结构中的成员可以使用相同的名字。
结构可以嵌套。
例: struct<span style="white-space:pre"> </span>rectangle { <span style="white-space:pre"> </span>struct<span style="white-space:pre"> </span>point p1; <span style="white-space:pre"> </span>struct<span style="white-space:pre"> </span>point p2; } 成员的引用为: <strong>rectangle.p1.x</strong>
二、结构与函数
结构的合法操作为:
- 整体复制和赋值(包括向函数传递参数及返回值)
- &运算符取地址
- 访问成员
例: struct<span style="white-space:pre"> </span>point makepoint( int x, int y) { <span style="white-space:pre"> </span>struct<span style="white-space:pre"> </span>point temp; <span style="white-space:pre"> </span>temp.x<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>x; <span style="white-space:pre"> </span>temp.y<span style="white-space:pre"> </span>=<span style="white-space:pre"> </span>y; <span style="white-space:pre"> </span>return<span style="white-space:pre"> </span>temp; }
注意:参数名与结构成员名重名不会冲突,还可强化之间联系。
三、结构指针
<strong><span style="color:#cc66cc;">struct<span style="white-space:pre"> </span>point* pp;</span></strong>
定义了一个指针pp指向struct point类型。此时,*pp即为该结构整体。
成员引用形式为:
(* pp).x或者 pp -> x
四、结构数组
<strong><span style="color:#cc33cc;">struct<span style="white-space:pre"> </span>point { <span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>x; <span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>y; }point_array[5];</span></strong>
point_array[5]即为结构数组。
五、结构长度
结构的长度不是简单的各成员长度的和。不同的对象有不同的对齐要求,所以结构中会出现未命名的“空穴(hole)”。例: struct { <span style="white-space:pre"> </span>char<span style="white-space:pre"> </span>c; <span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>i; } int占4字节,char占1字节。最后整个结构体可能是8个字节。
注意: 指针的长度由CPU决定,不取决于所指向的类型。
六、自引用结构
一个结构内不能包含自身,但是可以包含指向自身的指针。
例: struct<span style="white-space:pre"> </span>tnode { <span style="white-space:pre"> </span>char*<span style="white-space:pre"> </span>word; <span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>count; <span style="white-space:pre"> </span>struct<span style="white-space:pre"> </span>tnode* left; <span style="white-space:pre"> </span>struct<span style="white-space:pre"> </span>tnode* right; }
七、类型定义(typedef)
typedef 类型名 自定义类型名
例:
typedef<span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>A;<span style="white-space:pre"> </span>A a;声明一个int型变量a。 typedef int*<span style="white-space:pre"> </span>B;<span style="white-space:pre"> </span>B b;声明一个指向int型的指针b。 typedef structpoint <span style="white-space:pre"> </span>C;<span style="white-space:pre"> </span>C c;声明一个结构变量c。 typedef structpoint*<span style="white-space:pre"> </span>D;<span style="white-space:pre"> </span>D d;声明一个指向结构的指针d。
八、联合
<strong><span style="color:#cc66cc;">union 联合标记 { <span style="white-space:pre"> </span>成员 }联合名;</span></strong>
一个变量可以合法地保存多种数据类型中任一种类型的对象。这些类型中的任一种类型的对象都可赋值给 联合名,且可在后续表达式中使用,但必须保持一致。提供一种方式,可以在单块存储区中管理不同类型的数据。 所有成员相对于基地址的偏移量都为0。例: union<span style="white-space:pre"> </span>u_tag { <span style="white-space:pre"> </span>int<span style="white-space:pre"> </span>ivar; <span style="white-space:pre"> </span>float<span style="white-space:pre"> </span>fvar; <span style="white-space:pre"> </span>char*<span style="white-space:pre"> </span>cvar_p; }var; var可以是int、float、char*型。而不像int var一样,只是int型。
访问方式同结构。
联合可以使用在结构和数组中,反之亦可。
九、位字段(bit-field)
struct { <span style="white-space:pre"> </span>类型名<span style="white-space:pre"> </span>字段名1 : 宽度; <span style="white-space:pre"> </span>类型名<span style="white-space:pre"> </span>字段名2 : 宽度; <span style="white-space:pre"> </span>...... <span style="white-space:pre"> </span>类型名<span style="white-space:pre"> </span>字段名n : 宽度; }变量名;
宽度为二进制位数; 类型名只能为unsigned int、int、signed int。定义的字段最多 2 bytes,即 1 word。可以有 无名字段(只有冒号和宽度),起到填充的作用。字段的分配是看具体机器,有些从左至右,有些从右至左。字段不能使用&取址符。其引用同结构。例: struct { <span style="white-space:pre"> </span>unsignedint a : 1; <span style="white-space:pre"> </span>unsignedint b : 1; <span style="white-space:pre"> </span>unsignedint c : 1; }tag; 定义了一个变量tag,包含 3 个 1 bit 的字段。
位字段不能跨机器字存储,如果上一个机器字空间不足,将全部存到下一个机器字。