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标准类型的别名或缩写。

相关文章
|
9天前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
23 10
|
8天前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
13天前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
13天前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
17天前
|
编译器 C语言 C++
C语言结构体
C语言结构体
20 5
|
22天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
30 3
|
13天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
30 10
|
6天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
12天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
35 7
|
12天前
|
存储 编译器 程序员
【c语言】函数
本文介绍了C语言中函数的基本概念,包括库函数和自定义函数的定义、使用及示例。库函数如`printf`和`scanf`,通过包含相应的头文件即可使用。自定义函数需指定返回类型、函数名、形式参数等。文中还探讨了函数的调用、形参与实参的区别、return语句的用法、函数嵌套调用、链式访问以及static关键字对变量和函数的影响,强调了static如何改变变量的生命周期和作用域,以及函数的可见性。
24 4