C语言学习——结构

  • 结构
  • 结构的基本知识
  • 结构与函数
  • 结构数组
  • 指向结构的指针
  • 自引用结构
  • 表查找
  • 类型定义(typedef)
  • 联合
  • 位字段


结构

结构是一个或多个变量集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下。(某些语言将结构称为“记录”,比如Pascal语言。)

ANSI标准在结构方面最主要的变化是定义了结构的赋值操作——结构可以拷贝、赋值、传递给函数,函数也可以返回结构类型的返回值。

结构的基本知识

struct point
{
	int x;
	int y;
};

struct point pt;
struct { ... } x, y, z;
struct后面的名字是可选的,称为结构标记。
结构标记用于为结构命名。
结构中定义的变量称为成员。
结构成员,结构标记和普通变量(即非成员)可以采用相同的名字,它们之间不会冲突,因为通过上下文分析总可以总可以对它们进行区分。

结构声明后带变量表,需为其分配空间.不带,则不必为其分配空间。

结构与函数

结构的合法操作只有几种:作为一个整体复制和赋值,通过&运算符取地址,访问其成员。

传递结构的方法:

一是分别传递各个结构成员
二是传递整个结构
三是传递指向结构的指针


struct point* pp;
将pp定义为一个指向struct point类型对象的指针。

(*pp).x中圆括号是必须。
*pp.x等价于*(pp.x),因为x不是指针,所以该表达式是非法的。

结构指针使用频度非常高,为了使用方便,C语言提供了另一种简写形式。

设p是一个指向结构的指针,可用
	p->结构成员

运算符. 和 -> 都是从左到右结合

结构数组

struct key 
{
	char *word;
	int count;
} 
keytab[] 
= 
{
	"auto", 0,
	"break", 0,
	"case", 0,
	"char", 0,
	"const", 0,
	"continue", 0,
	"default", 0,
	/* ... */
	"unsigned", 0,
	"void", 0,
	"volatile", 0,
	"while", 0
};

或如下形式
	{ "auto", 0 },
	{ "break", 0 },
	{ "case", 0 },

// 字节单位大小,类型size_t
// 对象可以是变量,数组,结构
// 返回指定对象或类型占用的存储空间字节数
// 对数组对象或类型,统计数组所有元素整体占据的存储空间
sizeof object
// 类型可为基础类型,派生类型,指针
sizeof (type name)
...

指向结构的指针

自引用结构

统计输入中所有单词的出现次数。
一种解决方法是,在读取输入中任意单词的同时,就将它放置到正确的位置,从而始终保证所有单词是按顺序排列的。
另一种是使用二叉树的数据结构。

自引用结构的变体:两个结构相互引用。

表查找

数组的每个元素指向某个链表的表头,链表中的各个块用于描述具有该散列值的名字。如果没有名字散列到该值,则数组元素的值为NULL。

链表中的每一块都是一个结构,它包含一个指向名字的指针、一个指向替换文本的指针以及一个指向链表后继块的指针。
如果指向链表后继块的指针为NULL,则表明链表结束。

类型定义(typedef)

typedef 用来建立新的数据类型名。
如:

typedef int Length;

将Length定义为与 int 具有同等意义的名字。

注意,typedef 中声明的类型在变量名的位置出现,而不是紧接在关键字typedef 之后。
typedef 在语法上类似于存储类extern、static等。
在这里用大写字母作为typedef 定义的类型名的首字母,以示区别。

typedef 可以使程序参数化,以提高程序的可移植性。
typedef 的第二个作用是为程序提供更好的说明性——Treeptr 类型显然比一个声明为指向复杂结构的指针更容易让人理解。

联合

联合是可以(在不同时刻)保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求。
联合提供了一种方式,以在单块存储区中管理不同类型的数据,而不需要在程序中嵌入任何同机器有关的信息。
它类似于Pascal语言中的变体记录。

通过下列语法访问联合中的成员:

联合名.成员
或
	联合指针->成员

联合就是一个结构,它的所有成员相对于基地址的偏移量都为0,此结构空间要大到足够容纳最“宽”的成员,并且,其对齐方式要适合于联合中所有类型的成员。
对联合允许的操作与对结构允许的操作相同:作为一个整体单元进行赋值、复制、取地址即访问其中一个成员。
联合只能用其第一个成员类型的值进行初始化。

位字段

在存储空间很宝贵的情况下,有可能需要将对各对象保存在一个机器字中。
一种常见方法是,使用类似编译器符号表的单个二进制位标志集合。
外部强加的数据格式(如硬件设备接口)也经常需要从字的部分位中读取数据。

程序中的每个标识符都有与之相关的特定信息,例如,它是否为关键字,它是否是外部的且(或)是静态的,等等。
对这些信息进行编码的最简洁的方法就是使用一个char 或 int 对象中的位标志集合。

C语言提供了两一种可替代的方法,即直接定义和访问一个字中的位字段的能力,而不需要通过按位逻辑运算符。

位字段(bit-field),或简称字段,是“字”中相邻的集合。
“字”(word)是单个的存储单元,它同具体的实现有关。

学习参考资料:

《C程序设计语言》第2版  新版