C Primer Plus: 第十四章 结构和其他数据形式

C Primer Plus: 第十四章 结构和其他数据形式

14.2 建立结构声明

struct book {
    char title;
    char author;
    int value;
};
struct book library;
  • 该声明只描述了该对象由什么组成,称之为模板。(区别C++中的模板)
  • 右花括号后面的分号是必需的,表示结构布局定义结束。可以将声明放在所有函数的外部,也可以放在一个函数定义的内部。如果放在函数内部,则它的标记就只限于函数内部使用。
  • 声明结构变量时,struct不可以省略,在C++中可以省略。

14.3 定义结构变量

  • 初始化结构的语法与初始化数组的语法类似:
struct book library={
"the book name",
"Renene",
14
};
  • 使用在一对花括号括起来的初始化列表进行初始化,各初始化项用逗号分隔。或者使用点运算符和成员名标识特定的元素。
//只初始化部分成员
struct book sur = {.value = 10};
//乱序
struct book git = {
.value = 25,
.author = "Jame',
.title = "abs"
};
  • 自动储存类别对象的信息被储存在栈(stack)中。

14.6 指向结构的指针

  • 选择指针的原因:
    1. 指向结构的指针通常比结构本身更容易操控。
    2. 传递指针通常更有效率。
  • 一个结构的大小可能大于它的各成员大小之和。这是因为系统对数据进行校准的过程中产生了一些“缝隙”。例如,有些系统必须把每个成员都放在偶数地址上,或4的倍数的地址上。在这种系统中,结构的内部就存在未使用的“缝隙”。
  • 如何选择是使用结构指针还是结构:
    1. 把大型结构传递给函数,而函数只使用一两个成员时————传递指针或者只传递函数所需的成员更合理.
    2. 对于小型结构,使用按值传递结构。

14.7 其他结构特性

  • 现在的C允许把一个结构赋值给另一个结构,但是数组不能这样子做。
  • 赋值时,会把结构的每一个成员的值都赋给另一个成员。即使成员是数组,也能完成赋值。
  • 可以把一个结构初始化为相同类型的另一个结构。
伸缩型数组成员:
  • 第一个特性是,该数组不会立即存在。
  • 第二个特性是,使用这个伸缩性数组成员可以编写合适的代码,就好像它确实存在并具有所需数目的元素一样。
  • 规则:
    1. 伸缩型数组成员必须是结构的最后一个成员;
    2. 结构中必须至少有一个成员;
    3. 伸缩数组的声明类似于普通数组,只是它的方括号是空的。
struct flex
{
    int count;
    double ave;
    double scores[];    //伸缩型数组成员
}
//请求为一个结构和一个数组分配存储空间
//假设用score表示一个内含5个double类型值的数组
struct flex * pf;
pf = malloc(sizeof(struct flex)+5*sizeof(double));
  • 处理要求:
    1. 不能用结构进行赋值或拷贝。这种做法只能拷贝除伸缩型数组成员以外的其他成员。确实要进行拷贝,应使用memcpy()函数。
    2. 不要以按值方式把这种结构传递给结构。原因如1,需要把结构的地址传递给函数。
    3. 不要使用带有伸缩数组成员的结构座位数组成员或另一个结构的成员。

14.8 把结构内容保存到文件中

  • 使用fread()和fwrite()函数读写结构大小的单元。
fwrite(&primer, sizeof(struct book), 1, pbooks);
//&primer定位到primer结构变量开始的位置
//sizeof(struct book)告诉函数一块数据的大小
//1表示一次拷贝一块数据
//pbook标识一个文件流
  • fread()函数从文件中拷贝一块结构大小的数据到&primer指向的位置。简而言之,这两个函数一次读写整个记录,而不是一个字段。
  • rewind(pbook)函数确保文件指针位于文件开始处。为读文件做好准备。

14.10 联合简介

  • 联合(union)是一种数据类型,它能在同一个内存空间中存储不同的数据类型(不是同时储存)
  • 典型用法是,设计一种表示以储存既无规律、事先也不知道顺序的混合模型。每个联合可以储存各种数据类型。
  • 创建联合和创建结构的方式相同,需要一个联合模板和联合变量。
union hold{
    int digit;
    double bigfl;
    char letter;
};
union hold fit;
union hold save[10];
fit.letter = 'h';
fit.digit = 23; //清除h,存储23
fit.bigfl = 2.0; //清除23,存储2.0
  • 以上声明的联合只能储存一个int类型的值或一个double类型的值或char类型的值。即使有足够空间,也只能储存一个值。
  • 编译器分配足够的控件以便它能储存联合声明中占用最大字节的类型。

14.11 枚举类型

  • 可以用枚举类型声明符号名称来表示整型常量。实际上,enum常量是int类型。
  • 枚举类型的目的是提高程序的可读性。它的语法与结构的语法相同。
  • 常用于case语句中。
enum spectrum{red, orange, yellow, green, blue, violet};
enum spectrum color;
color = blue;
if(color == yellow)...
  • 默认情况下,枚举列表中的常量被赋予0,1,2等
  • 在枚举声明中,可以为枚举常量指定整数值:
enum levels {low=100, medium=500, high=2000};
  • 如果只给一个枚举常量赋值,没有对后面的枚举常量赋值,那么后面的常量会被赋予后续的值。

typedef简介

  • 利用typedef可以为某一类型自定义名称。目的是为经常出现的类型创建一个方便、易标识的类型名。
  • 这方面与#define类似,但两者有3出不同:
    1. 与#define不同,typedef创建的符号名只受限于类型,不能用于值
    2. typedef由编译器解释,不是预处理器。
    3. 在其受限范围内,typedef比#define更灵活
  • 例:
typedef unsigned char BYTE;
BYTE x, y[10];
  • #define只是简单的替换,如下面
#define STRING char *
STRING name, sing;
//翻译成
char * name, sign;
//这导致只有name是指针

14.14 函数和指针

  • 可以声明一个指向函数的指针,传递给另一个函数,告诉该函数要使用哪个函数。
  • 指向函数的指针中储存着函数代码的起始处的地址。
  • 声明一个函数指针时,必须声明指针指向的函数类型。为指明函数类型,要指明函数签名,即函数的返回类型和参数类型。
void ToUpper(char *);

void (*fp)(char *);
  • 要声明一个指向特定类型函数的指针,可以先声明一个该类型的函数,然后把函数名替换成(*pf)形式的表达式。然后pf就成为指向该类型函数的指针。
  • 调用方法:
    1.(*fp)(arg);
    2.fp(arg);
  • 作为函数参数的原型:
void show(void (*fp)(char *), char * str);
  • fp形参是一个函数指针,str是一个数据指针。

ANSI C是什么

  • 第一个C标准由ANSI发布,ISO进行完善
  • ANSI C
  • ISO C
  • Standard C
  • 都是C语言的一些标准
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值