C语言结构
![水墨上水](https://img-blog.csdnimg.cn/direct/246aa80e974142bcb7f63a0a39be192e.jpeg#pic_center)
苍色 水色 玄青
第 一 章 结构
- 结构的涵义
结构的涵义,是能够把一些零散而相关的、相同类型或不同数据揉搓一起,用一个名字来引用他们。结构声明只是声明一个类型的框架结构,而结构名(该结构变量)分配了该结构类型的内存空间。
- 结构的基础知识
struct 可选标记名 {
一系列声明;
}可选声明变量表;
- 结构名
结构标记是可选的,结构定义之后,标记代表花括号的内容。 使用 struct+结构标记,就能为结构定义一种变量名了。
- 结构成员
在结构中,花括号内的一系列声明是结构成员,使用时“结构名+ . (结构成员运算符)+结构成员”就可引用某个成员。
- 结构的初始化
可在可选声明变量表里进行结构成员初始化,用花括号里一组常量表达式对结构成员从上往下依次赋值。也可如此:“struct+结构标记+结构名 = {常量表达式1,……,常量表达式n};”。
- 结构嵌套
一个结构里,可以声明另一个结构名,使用结构成员方法类似。嵌套几层变量前加几个结构成员运算符或初始化时在另加几层花括号。
- 命名注意事项
结构标记和非成员变量取相同名字,结构标记通常和结构声明“struct”一起出现,因此不会冲突;不同结构之间的结构成员名字可以相同。
- 示例代码
#include <stdio.h>
struct point {
int x;
int y;
};
struct point coord = {100,200};
struct rectangle {
struct point rect1;
struct point rect2;
}yy;
yy.rect2.y = 1024;
int main ()
{
printf (“coord.x,coord.y = %d,%d\n”,coord.x,coord.y);
printf (“yy.rect2.y = %d\n”,yy.rect2.y);
printf (“yy.rect2.x = %d\n”,yy.rect2.x);
return 0;
}
温馨提示:手动输入代码,要方便许多!
- 结构名
第 二 章 结构与函数
- 结构的合法操作
对结构可以进行三种合法操作:首先可整体复制和赋值结构;对结构成员具体的赋值和复制;使用指向结构的指针,间接使用结构。
总的来说,引用结构名就是在操作整个结构,也可直接具体引用结构成员做某事,再者可引用指向结构的指针操作结构。
- 结构与函数
问题?结构名和数组名一样吗?结构之间不可比较运算。
- 结构的整体复制与函数
我们已学得,函数与外界信息交换方式是值传递。结构名代表整个结构,只能在同类型结构之间进行复制,使用“结构名 = 结构名”即可,之后使用成员运算符对成员操作。
所谓,结构复制操作,重点是“复制”,使两者一模一样。不管是作为参数数,还是函数返回值都可。
- 结构的赋值与函数
结构的赋值操作,是对结构成员一一操作,是精确赋值。在函数中常常要对结构成员精确操作,比如这个成员要给个什么值、这个成员的值又传给谁。
- 指向结构的指针
结构指针,不能像指向数组的指针一样,可有效进行地址运算。指针的可见好处是,只要拥有某个对象的地址,间接操作对象灰常方便。下面是结构指针的操作方法:
成员运算符方法——(*结构指针变量).成员名,指针间接引用结构,再寻找该结构的成员。运算符优先级。
结构指针成员访问符“->”——指针->成员名,该运算符是结构指针专用,等同 上一个方法,是很简便直观。
- 结构的整体复制与函数
第 三 章 结构数组
数组的定义很简单,同类型数据对象的地址连续的集合。 声明形式:结构名[]- 初始化
如果初始化值是简单的常量或字符串,并且结构数组的任何初始值不为空,初始化列表里可省略内层花括号。
一般形式:结构名[] = {{常量表达式列表},{},……,{}};
- 编译时对象长度计算
数组初始化时没有指定大小,编译程序会计算初始化列表的元素个数类确定数组大小,C语言提供了编译时一元运算符关键字“sizeof”,它可计算任一对象的长度:
sizeof 对象
sizeof(类型名)
sizeof 可以出现在宏里面,因为宏指令在预处理阶段不做任何运算,只做简单替换。结构数组的长度:“#define 结构数组长度 (sizeof 结构数组名 / sizeof 结构数组名[0])”。
第 四 章 指向结构的指针
- 结构指针
结构指针对构成复杂的数据对象非常有用。
- 结构大小
结构的大小不是简单成员之和,而是以成员最大空间来对齐。
- 数组中地址之间的运算
数组的引用,不管是通过下标还是指针都是非法的,C语言保证数组末尾后的一位,可有效进行地址间的减法运算正确。
- 函数声明和定义书写格式
一般形式:函数返回类型 函数名 (参数表)
另一种形式:
函数返回类型
函数名 (参数表)
第 五 章 自引用结构
- 自引用结构
“自引用”,引用的意思是,通过某个对象的地址,引用该对象的的数据;自引用,不就是访问自己的地址里面的数据吗?因此,自引用结构的涵义是,通过本结构指针访问自己。
自引用结构为啥不能直接引用本身呢?那是有递归循环,没有确定性,无法定义。
- 互引用结构
互引用结构,是“你中有我,我中有你”的相互包含这对方的结构指针。
- 自引用结构的应用——二叉树
树形结构,像树一样,从根发散很多个枝桠。每个发散点是一个节点,树的根是根节点(root);任意一个节点最多拥有2个子树,也可只有1个或0个子树,每个子树是一个节点,子树分为左子树和右子树。
- 二叉树节点的生成
二叉树的节点,既是节点,又是上一个节点的子树。因为每个节点(左右子树)的产生,都是遵循同一个规则,所以,使用递归方法很自然。树的节点生成规则自己选择。
- 二叉树的遍历
二叉树的遍历,通常与生成方式相呼应。
一个书中例子,统计所有单词出现频率。
- 二叉树节点的生成
第 六 章 链表
- 自引用结构的应用——链表
没错,自引用结构还可构建“链表”结构。链表是由两部分组成的,一是另一个该类型的指针,二是数据部分。
struct link {
char *date;
struct link *next;
};
- 哈希表(hash table)
哈希表是一种数据结构,通过散列(音译,哈希)函数把数据计算成一个数值,根据这个值相对应的数据建立一个表;想要查询某个数据,就计算哈希值,通过此值直接寻找数据。
下列是哈希表和链表的合作,只不过使用链表时,只使用表头。
struct nlist {
struct nlist *next;
char *name;
char *defn;
};
struct nlist *hashtab[];/ * 哈希表 * /
首先通过散列函数生成哈希值,其次把链表中的指针赋值为NULL(不使用完整链表),最后把宏替换信息录入链表中,哈希值作为数组下标,链表数据写入当前数组位置。
注:这里会涉及到链表遍历的方法,所以本书案例是让读者即学习链表,又学习了哈希表。
第 七 章 类型定义(typedef)
类型定义,就是为已有类型,自定义一个类似于基本类型样式的别名。通常为结构定义别名。typedef 已有类型 替换类型名
注:数组和指针,有点东西!解释行为,其他都是类型的描述,标识符就是新名字,如:
这感觉顺序不对啊?是这样解释的,首先是个指针,是函数指针,这里描述的是怎样的指针,然后标识符是替换这样的函数指针。记住,typedef是类型定义,先解读什么样的类型,然后把标识符作为新类型名!
是不是有点类似宏替换?类型定义是编译器解释的,而宏替换是编译前预处理器解释的!但是,typedef 比宏替换更强大。
第 八 章 联合
联合是一种结构,是以成员们最大储存空间的长度和对齐分配一个地址空间,也就是不同时刻共享同一内存! 引用联合和结构一样,嵌套什么的,都可;联合名.成员、联合指针->成员。同一刻,只能引用一个成员(程序只会使用最近赋值的联合成员)。- 联合初始化
联合只能用第一个成员类型的值初始化!
第 九 章 位字段
位字段是多个对象保存再机器字中的。- 目的
存储空间很宝贵、需要对位操作。
- 性质
1.位字段中的“字”是,单个储存单元,就是一个对象;该对象只能是整形,字表示计算机一次能处理多少位;位字段中字大小取决于具体实现,比如64位计算机上,编译器选择32位系统,所以该字的大小是4个字节。
2.位字段可以出现再算术表达式中。
3.字段可以不命名,称为无名字段,用于填充字的剩余位;特殊宽度0用于强制下一个位字段在下一个字边界对齐分配位。
4.字段的位分配有可能不同,有的机器是从字边界的左端到右端分配,反之亦有,依赖这些因素的程序不可移植。
5.字段的成员的类型仅仅为整形(int),通常方便移植,需显示声明是signed 、unsigend。
6.位字段没有地址,取地址和指针都不可用。
学习笔记真难搞!