C语言结构体和其他数据形式(C Primer Plus 第六版)(三)

简介: C语言结构体和其他数据形式(C Primer Plus 第六版)(三)

七、联合简介



联合(union)是一种数据类型,它能在同一个内存空间中储存不同的数据类型(不是同时储存)。其典型的用法是,设计一种表以储存既无规律、事先也不知道顺序的混合类型。使用联合类型的数组,其中的联合都大小相等,每个联合可以储存各种数据类型。


创建联合和创建结构的方式相同,需要一个联合模板和联合变量。可以用一个步骤定义联合,也可以用联合标记分两步定义。下面是一个带标记的联合模板:


union hold {
int digit;
 double bigfl;
 char letter;
};


根据以上形式声明的结构可以储存一个int类型、一个double类型和char类型的值。然而,声明的联合只能储存一个int类型的值或一个double类型的值或char类型的值。


下面定义了3个与hold类型相关的变量:


union hold fit; // hold类型的联合变量


union hold save [10]; //内含10个联合变量的数 union hold * pu; //指向hold类型联合变量的指针


第1个声明创建了一个单独的联合变量fit。编译器分配足够的空间以便它能储存联合声明中占用最大字节的类型。在本例中,占用空间最大的是double类型的数据。在我们的系统中,double类型占64位,即8字节。第2个声明创建了一个数组save,内含10个元素,每个元素都是8字节。第3个声明创建了一个指针,该指针变量储存hold类型联合变量的地址。


7.1 联合和结构体的区别


联合体

用途:使几个不同类型的变量共占一段内存(相互覆盖)


结构体是一种构造数据类型

用途:把不同类型的数据组合成一个整体-------自定义数据类型


八、枚举类型



一个集的 枚举 是列出某些有穷 序列 集的所有成员的程序,或者是一种特定类型对象的计数。


可以用枚举类型((enumerated type)声明符号名称来表示整型常量。使用enum关键字,可以创建一个新“类型”并指定它可具有的值(实际上,enum常量是int类型,因此,只要能使用int类型可以使用枚举类型)。枚举类型的目的是提高程序的可读性。它的语法与结构的语法相同。例如,可以这样声明:


enum spectrum (red,orange,yellow,green,blue,violet} ;
 enum spectrum color;


第1个声明创建了spetrum作为标记名,允许把enum spetrum作为一个类型名使用。第2个声明使color作为该类型的变量。第1个声明中花括号内的标识符枚举了spectrum变量可能有的值。因此,color可能的值是red、orange、yellow 等。这些符号常量被称为枚举符(enumerator)。然后便可这样用:


int c;
color = blue;
if (color == yellow)


8.1 enum的用法


枚举类型的目的是为了提高程序的可读性和可维护性。如果要处理颜色,使用red和 blue 比使用0和1更直观。注意,枚举类型只能在内部使用。如果要输入color中orange的值,只能输入1,而不是单词orange。或者,让程序先读入字符串"orange",再将其转换为orange 代表的值。


因为枚举类型是整数类型,所以可以在表达式中以使用整数变量的方式使用enum变量。它们用在case语句中很方便。


九、typedef简介



typedef 工具是一个高级数据特性,利用typedef可以为某一类型自定义名称。这方面与#define类似,但是两者有3处不同:


与#define不同,typedef创建的符号名只受限于类型,不能用于值。


typedef由编译器解释,不是预处理器。


在其受限范围内,typedef 比#define更灵活。


下面介绍typedef的工作原理。假设要用BYTE表示1字节的数组。只需像定义个char 类型变量一样定义BYTE,然后在定义前面加上关键字typedef 即可:


typedef unsigned char BYTE;


随后,便可使用BYTE来定义变量:


BYTE x, y [10],* Z;


该定义的作用域取决于typedef定义所在的位置。如果定义在函数中,就具有局部作用域,受限于定义所在的函数。如果定义在函数外面,就具有文件作用域。


通常,typedef定义中用大写字母表示被定义的名称,以提醒用户这个类型名实际上是一个符号缩写。当然,也可以用小写:


typedef unsigned char byte;


typedef中使用的名称遵循变量的命名规则。


为现有类型创建一个名称,看上去真是多此一举,但是它有时的确很有用。在前面的示例中,用BYTE代替unsigned char表明你打算用BYTE类型的变量表示数字,而不是字符码


typedef的一些特性与#define的功能重合。例如:


#define BYTE unsigned char


这使预处理器用BYTE替换unsigned char。但是也有#define没有的功能:


typedef char * STRING;


**没有typedef关键字,编译器将把STRING识别为一个指向char的指针变量。有了typedef关键字,编译器则把STRING解释成一个类型的标识符,该类型是指向char的指针。**因此:


STRING name,sign ;


相当于:


*char name, * sign ;


但是,如果这样假设:#define STRING char *然后,下面的声明:

STRING name,sign;


将被翻译成:


char *name, sign;


这导致只有name才是指针。


还可以把typedef用于结构:


typedef struct complex {
 float real;
 float imag;
}COMPLEX;


然后便可使用COMPLEX类型代替complex结构来表示复数。使用typedef 的第1个原因是

**为经常出现的类型创建一个方便、易识别的类型名。**例如,前面的例子中,许多人更倾向于使用STRING或与其等价的标记。


用typedef来命名一个结构类型时,可以省略该结构的标签:


typedef struct ( double x; double y; } rect;


假设这样使用typedef定义的类型名:


rect r1= { 3.0,6.0 ) ;
rect r2 ;


以上代码将被翻译成:


struct { double x; double y; } r1= { 3.0, 6.0 };
struct { double x; double y; } r2;
r2 = r1;


这两个结构在声明时都没有标记,它们的成员完全相同(成员名及其类型都匹配),C认为这两个结构的类型相同,所以r1和r2间的赋值是有效操作。


使用t ypedef的第2个原因是: t**ypedef常用于给复杂的类型命名。*例如,下面的声明;typedef char ( FRPTC ())[5];

把FRPTC声明为一个函数类型,该函数返回一个指针,该指针指向内含5个char类型元素的数组(参见下一节的讨论)。


使用typedef时要记住,**typedef并没有创建任何新类型,它只是为某个已存在的类型增加了一个方便使用的标签。**以前面的STRING为例,这意味着我们创建的STRING类型变量可以作为实参传递给以指向char指针作为形参的函数。

通过结构、联合和typedef,C提供了有效处理数据的工具和处理可移植数据的工具。


十、关键概念



我们在编程中要表示的信息通常不只是一个数字或一些列数字。程序可能要处理具有多种属性的实体。例如,通过姓名、地址、电话号码和其他信息表示一名客户;或者,通过电影名、发行人、播放时长、售价等表示一部电影DVD。C结构可以把这些信息都放在一个单元内。在组织程序时这很重要,因为这样可以把相关的信息都储存在一处,而不是分散储存在多个变量中。


设计结构时,开发一个与之配套的函数包通常很有用。例如,写一个以结构(或结构的地址)为参数的函数打印结构内容,比用一堆printf()语句强得多。因为只需要一个参数就能打印结构中的所有信息。如果把信息放到零散的变量中,每个部分都需要一个参数。另外,如果要在结构中增加一个成员,只需重写函数,不必改写函数调用。这在修改结构时很方便。


联合声明与结构声明类似。但是,联合的成员共享相同的存储空间,而且在联合中同一时间内只能有一个成员。实质上,可以在联合变量中储存一个类型不唯一的值。


enum 工具提供一种定义符号常量的方法,typedef 工具提供一种为基本或派生类型创建新标识符的方法。


指向函数的指针提供一种告诉函数应使用哪一个函数的方法。(这个文章没有更新,用的不多,有需要的话再回来更新)


十一、总结



C结构提供在相同的数据对象中储存多个不同类型数据项的方法。可以使用标记来标识一个具体的结构模板,并声明该类型的变量。通过成员点运算符(.)可以使用结构模版中的标签来访问结构的各个成员。


如果有一个指向结构的指针,可以用该指针和间接成员运算符(->)代替结构名和点运算符来访问结构的各成员。和数组不同,结构名不是结构的地址,要在结构名前使用&运算符才能获得结构的地址。


一贯以来,与结构相关的函数都使用指向结构的指针作为参数。现在的C允许把结构作为参数传递,作为返回值和同类型结构之间赋值。然而,传递结构的地址通常更有效。


联合使用与结构相同的语法。然而,联合的成员共享一个共同的存储空间。联合同一时间内只能储存一个单独的数据项,不像结构那样同时储存多种数据类型。也就是说,结构可以同时储存一个int 类型数据、一个double类型数据和一个char类型数据,而相应的联合只能保存一个int类型数据,或者一个double类型数据,或者一个char类型数据。


通过枚举可以创建一系列代表整型常量(枚举常量)的符号和定义相关联的枚举类型。


typedef 工具可用于建立C标准类型的别名或缩写。

相关文章
|
19天前
|
存储 程序员 编译器
C 语言中的数据类型转换:连接不同数据世界的桥梁
C语言中的数据类型转换是程序设计中不可或缺的一部分,它如同连接不同数据世界的桥梁,使得不同类型的变量之间能够互相传递和转换,确保了程序的灵活性与兼容性。通过强制类型转换或自动类型转换,C语言允许开发者在保证数据完整性的前提下,实现复杂的数据处理逻辑。
|
15天前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
83 14
|
19天前
|
存储 编译器 C语言
【C语言】结构体详解 -《探索C语言的 “小宇宙” 》
结构体通过`struct`关键字定义。定义结构体时,需要指定结构体的名称以及结构体内部的成员变量。
79 10
|
20天前
|
存储 数据管理 C语言
C 语言中的文件操作:数据持久化的关键桥梁
C语言中的文件操作是实现数据持久化的重要手段,通过 fopen、fclose、fread、fwrite 等函数,可以实现对文件的创建、读写和关闭,构建程序与外部数据存储之间的桥梁。
|
23天前
|
存储 数据建模 程序员
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
|
19天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
39 10
|
19天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
42 9
|
19天前
|
存储 Unix Serverless
【C语言】常用函数汇总表
本文总结了C语言中常用的函数,涵盖输入/输出、字符串操作、内存管理、数学运算、时间处理、文件操作及布尔类型等多个方面。每类函数均以表格形式列出其功能和使用示例,便于快速查阅和学习。通过综合示例代码,展示了这些函数的实际应用,帮助读者更好地理解和掌握C语言的基本功能和标准库函数的使用方法。感谢阅读,希望对你有所帮助!
31 8
|
19天前
|
C语言 开发者
【C语言】数学函数详解
在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
40 6
|
19天前
|
存储 C语言
【C语言】输入/输出函数详解
在C语言中,输入/输出操作是通过标准库函数来实现的。这些函数分为两类:标准输入输出函数和文件输入输出函数。
106 6