C语言中结构、联合、枚举的说明
复杂的数据类型
一般的步骤:
1、声明模板
2、定义变量,分配内存空间
3、初始化
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
标记、标识符、标签
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
结构:
设计程序很重要的一步是提高表示数据的能力,选择表示数据的方法。C提供了结构变量(structure variable)提高你表示数据的能力。
14.1 建立结构声明
结构声明(structure variable)描述了一个结构的组织布局。声明类似如下:
struct book{
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
该声明并未创建实际的数据对象,只描述了该对象由什么组成。(结构声明有时候称为模板)
关键字struct,表明跟在其后的是一个结构,后面是一个可选的标记。后面的程序可以根据标记引用该结构。如果打算重复使用该模板,就要使用带标记的形式。
用花括号括起来的是结构成员列表。
花括号后面的分号是必须的,表明结构布局定义结束。
14.2 定义结构变量
结构有两层含义。一层含义是“结构布局”,结构布局告诉编译器如何表示数据,但是它并未让编译器为数据分配空间。
下一步是创建一个结构变量,即是结构的另一层含义。
例如 struct book library;
编译器执行这行代码便创建了结构变量library。编译器使用book模板为该变量分配空间。解释:一个内含MAXTITL个元素的char数组,一个内含MAXAUTL个元素的char数组和一个float类型的变量;这些存储空间都与一个名称library结合在一起。struct book的作用相当于声明了一个int或float。
struct book相当于自定义了一种数据类型,这个数据类型用book作标记。程序可以根据标记引用该数据类型。
就计算机而言,声明:struct book library;
是以下声明的简化:
struct book{
char title[MAXTITL];
char author[AXAUTL];
float value;
}library;
声明结构的过程和定义结构变量的过程可以组合成一个步骤。
14.2.1 初始化结构
使用在一对花括号括起来的初始化列表进行初始化。各初始化项用逗号分隔。让每个成员的初始化项独占一行,这样做只是为了提高代码的可读性。对编译器而言,只需要用逗号分隔各成员的初始化项即可。
14.2.2 访问结构成员
结构类似于超级数组。超级数组中,可以是一个元素为char类型,一个元素为forat类型,一个元素为int数组。
数组可以通过数组下标单独访问数组中的各元素。
访问结构中的成员,可以使用结构成员运算符---->点(.)访问结构中的成员。
例如library.value即访问library中的value部分。可以像使用任何float类型变量那样使用library.value。library是一个结构,library.value是一个float类型的变量。
14.2.3 结构的初始化器
C99和C11为结构指定了初始化器。
struct book gift={
.value = 25.99,
.author = “James Broadfool”,
.title = “Rue for the Toad”
};
进一步了解结构的一些相关类型。
14.3 结构数组
14.3.1 声明结构数组
struct book library[MAXBKS];
14.3.2 标识结构数组的成员
library[0].value
library[4].title
14.3.3 程序讨论
14.4 嵌套结构
一个结构中包含另一个结构;
14.5 指向结构的指针
好处:1、指向结构的指针比结构本身更容易操控,就像指向数组的指针比指针本身更容易操控;2、早期C中,结构不能作为参数传递给函数,可以传递指向结构的指针;3、即使能传递结构,传递指针更有效率;4、一些用于表示数据的结构中包含指向其他结构的指针。
14.5.1 声明和初始化结构指针
声明结构指针:struct guy * him;
首先是关键字struct,其次是结构标记guy,然后是一个星号*,然后跟着指针名him;
结构名不是结构的地址,因此要在结构名前面加上&运算符;
例如fellow是结构数组,fellow[0]是一个结构,要让him指向fellow[0],可以这样写:
him = &fellow[0];
14.5.2 用指针访问成员
使用 ->运算符,访问结构中的成员;
him == &barney , 那么 him ->income 即是 barney.income
him == &fellow[0] , 那么 him ->income 即是 fellow[0].income
14.6 向函数传递结构的信息
ANSI C允许把结构作为参数使用。所以程序员可以选择传递结构本身,还是传递指向结构的指针。如果你只关心结构中某一部分,你可以把结构的成员作为参数。
14.6.1 传递结构成员
直接传递结构成员,其实被调函数根本不关心传递的实际参数是否是结构成员。
14.6.2 传递结构的地址
double sum(const struct funds *);
传递结构stan给函数,必须使用&运算符来获取结构的地址。&stan然后传递给函数。
14.6.3 传递结构
函数的形参直接是结构类型的形参,实参就是结构变量。
14.6.4 其他结构特性
结构允许把值赋值给另一个结构。
现在的C不仅能把结构本身作为参数传递,也能把结构作为返回值返回。
把结构作为函数参数可以把结构的信息传达给函数。
把结构作为返回值的函数能把结构的信息从被调函数返回主调函数。
结构指针允许这样的双向通信。
14.6.5 结构和结构指针的选择
把指针作为参数传递优点:执行起来很快,能兼容旧的和新的C,只需要传递一个地址。缺点是:无法保护数据。被调函数的某些操作可能会意外影响原来结构中的数据。不过ANSI C新增的限定符const解决了这个问题。
把结构作为参数传递的优点是:函数处理的是原始数据的副本,这保护了原始数据。另外,代码风格也更清楚。缺点是:较老版本可能无法处理这样的代码,传递结构浪费时间和存储空间,尤其是把大型结构传递给函数。
通常做法:为了追求效率使用结构指针作为函数参数,如需防止原始数据被意外修改,使用const限定符。按值传递结构是处理小型结构的最常见方法。
14.6.6 结构中的字符数组和字符指针
字符数组存储字符串
struct names{
char first[LEN];
char last[LEN];
};
指向char的指针来存储字符串
struct pnames{
char * first;
char * last;
};
struct names veep = {“Talia”,“Summers”};
struct pnames treas = {“Brad”,“Fallingjaw”};
对于struct name类型的变量veep来说,以上字符串都储存在结构内部;这种做法比较占空间。
对于struct pnames类型的变量treas来说,字符串储存在编译器储存常量的地方。结构本身只储存了两个地址。
如果pnames类型的变量treas未经初始化,地址可以是任何值,这一操作可能导致程序奔溃。
因此,如果要用结构储存字符串,用字符数组比较简单。用指向char的指针也行,但是误用会导致严重问题。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
联合:
联合(union)是一种数据类型,它能在同一个内存空间中储存不同的数据类型(不是同时储存)。
典型用法:设计一种表以储存既无规律、事先也不知道顺序的混合类型。使用联合类型的数组,其中的联合都大小相等,每个联合可以储存各种数据类型。
创建联合和创建结构的方式相同,需要一个联合模板和联合变量。
先定义一个带标记的联合模板;
union hold{
int digit;
double bigfl;
char letter;
}
声明一个单独的联合变量fit,会按照占用空间最大的数据类型分配空间;
union hold fit; //声明一个联合变量fit;\
联合的初始化:只能初始化一个值。
14.9.1 使用联合
在联合中,一次只储存一个值。即使有足够的空间,也不能同时储存一个char类型和一个int类型。
fit.digit = 23; //把23储存在fit,占2个字节
fit.bigfl = 2.0; //清除23,储存2.0,占8个字节
fit.letter = ‘h’; //清除2.0,储存h,占1字节
用指针访问结构成员使用->运算符;
同样,用指针访问联合时也要使用->运算符;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
枚举:
枚举类型(enumerated type)用符号名称来表示整型常量。使用enum关键字。
枚举的目的是提高程序的可读性。语法与结构的语法相同。
声明:
enum spectrum {red, orange, yellow, green, blue, violet};
enum spectrum color;
第一条声明:spetrum是标记,允许把enum spectrum作为一个类型名使用。花括号内的标识符枚举了spectrum变量可能有的值。这些符号常量叫做枚举符。
第二条声明:color作为该类型的变量。
enum常量:
red=0,orange=1。从技术层面看,这些枚举符都是int类型的常量。
默认值:
默认情况下,枚举列表中的常量都被赋予0、1、2等。
赋值:
在枚举声明中,可以为枚举常量指定整数值。
enum level {low =100, medium =500, high=2000};
考虑以下情况:
enum feline {cat, lynx =10, puma, tiger};
那么cat的值是默认0,puma是11,tiger是12;
enum的用法:
枚举类型的目的是增强程序的可读性和可维护性。
注意,枚举类型只能在内部使用,如果要输入color中orange的值,只能输入1。而不是单词orange。或者,让程序先读入orange,在将其转换为orange代表的值。
枚举类型是整数类型,所以可以在表达式中以使用整数变量的方式使用enum变量。它们用在case语句中很方便。
共享名称空间:
C语言使用名称空间(namespace)来标识程序中的各部分,即通过名称来识别。作用域是名称空间概念的一部分:两个不同作用域的同名变量不冲突,两个相同作用域的同名变量冲突。
在特定作用域中,结构标记,联合标记,枚举标记都共享相同的名称空间,该名称空间与普通变量使用的空间不同。这意味着在相同作用域中变量和标记的名称可以相同,不会引起冲突。但是不建议使用相同的标识符,以免引起混乱。
注意,在C++中,把标记和变量名放在相同的名称空间中。
C语言中结构、联合、枚举的说明的更多相关文章
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- Go语言中结构体的使用-第2部分OOP
1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...
- 6. Go 语言中结构体的使用
1. 结构体的定义格式 在go语言中结果的定义格式如下: 123 type structName struct { filedList} 列子如下: 1234 type Person struct { ...
- C语言中结构体内存存储方式
C语言中结构体内存存储方式 结构体的默认存储方式采用以最大字节元素字节数对其方式进行对齐,例如一个结构体中定义有char.int类型元素,则结构体存储空间按照int类型占用字节,如果还有double类 ...
- C语言的结构体,枚举类型在程序中的作用
http://www.xue63.com/xueask-1221-12212854.html 结构和枚举类型从程序实现的角度来说,是用更接近自然语言的方式来表达数据.比如说实现2维空间的点,你可以使用 ...
- Go语言中结构体的使用-第1部分结构体
1 概述 结构体是由成员构成的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性.结构体成员,也可称之为成员变量,字段,属性.属性要满足唯一性.结构体的概念在软件工程上 ...
- c语言中结构体指针
1.指向结构体的指针变量: C 语言中->是一个总体,它是用于指向结构体,如果我们在程序中定义了一个结构体,然后声明一个指针变量指向这个结构体.那么我们要用指针取出结构体中的数据.就要用到指向运 ...
随机推荐
- UWP蓝牙的例子
https://answers.microsoft.com/zh-hans/windows/forum/windows_10-networking/%e5%9c%a8win10%e7%8e%af%e5 ...
- winform 打印
pageSetupDialog 打印设置,和对话框控件差不多的套路,把控件拖到窗口中后,会在下方显示, 然后在制作的菜单中找到打印设置,双击进入点击事件写代码 按照之前的套路, DialogResul ...
- OpenCV Mat数据类型指针ptr的使用
OpenCV Mat数据类型指针ptr的使用 cv::Mat image = cv::Mat(400, 600, CV_8UC1); //宽400,长600 uchar * data00 = imag ...
- 算法Sedgewick第四版-第1章基础-018一解决不能声明泛型数组的两咱方法(强转或反射)
1. /****************************************************************************** * Compilation: ja ...
- tomcat8.0的下载安装配置
配置tomcat前要先配置JDK的环境变量 具体方法请点链接JDK环境变量配置 首先要 到官网下载tomcat tomcat官网 进入官网后 如图在左侧选择自己想要下载的版本,这里我以8.0版本为例 ...
- p2234&bzoj1588 营业额统计
传送门 题目 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额 ...
- Luogu 4388 付公主的矩形
还是挺妙的. 发现对于一个$r$行$c$列的矩阵,穿过的格子数$n = r + c - gcd(r, c)$,题目中其实给定了这个$n$,要我们计算满足这个式子的$r$和$c$的个数. 发现$n$一定 ...
- Django框架 之 view视图
Django框架 之 view视图 浏览目录 概述 简单的视图 HttpRequest对象 CBV和FBV 给视图加装饰器 Request对象 Response对象 JsonResponse对象 Dj ...
- 转/keystore和truststore的区别
keytool是java自带的工具用于产生密钥 keystore可以看成一个放key的库,key就是公钥,私钥,数字签名等组成的一个信息. truststore是放信任的证书的一个store. 那他们 ...
- 数据结构_calculator
问题描述 小 V 发明了一个神奇的整数计算器:给定一个合法的表达式,这个计算器能求出这个表达式的最终答案.表达式可能包含:+:运算符,整数加法.如 1+1=2-:运算符,整数减法.如 1-1=0*:运 ...