第十四章 结构和其他数据形式
结构体的定义
无需多言,理解并熟练使用下面提到的几种形式.
标准:
struct VtStruct{
int i;
int b;
};
sturct VtStruct stDemo;
无标记:
struct {
int i;
int b;
} stDemo;
使用typedef:
typedef struct VtStruct{
int i;
int b;
}VtStruct;
VtStruct stDemo;
结构体的一些特性
ANSI C允许讲一个结构体赋值给另一个相同类型的结构体(就算结构体中的变量为数组也会
正确完成赋值).同时,结构体也可以作为参数传递给函数(值传递,传递的为副本,修改副本不
影响外部参数本身),也可以作为返回值从函数进行返回. 这里可以简单的谈一下将结构体
作为参数和将结构体指针作为参数的抉择问题.如果希望改变传入的参数本身,则使用结构体
指针,如果希望对外部数据进行保护,则使用结构体.
有关于union联合
联合是能在同一个存储空间内存储不同类型数据的数据类型.联合的具体定义和使用方式与
结构体类似.
union Demo {
int a;
double b;
};
这里还要讲一下联合的内存分配策略,简单地说,编译器分配足够的空间以保存所描述的可能
性的最大需要.在上例中,最大可能性是double b.因此联合的大小为8字节.
有关于枚举
枚举的最重要的作用就是它可以声明代表数量的类型(符号名称),可以提高代码的可读性.
枚举的值是自然增加的,如:
enum demo{
one,
two,
three
}
上例中one = 0, two = 1, three = 2;如不指定具体的值,枚举的值会一直这么加下去.若指
定值则是下种情况:
enum demo1{
one = 100,
two,
three = 200,
four
}
这里one = 100, two = 101, three = 200, four = 201.
typedef的说明
- typedef给出的符号名称仅限于对类型,而不是值.
- typedef的解释有编译器,而非预处理器执行.
下面来说一下经常与typedef共同使用的一些类型,变量声明方式的规则.
1. 表示一个数组的[]和表示一个函数的()具有同样的优先级,且[],()的优先级高于*;
2. []和()都是从左到右进行结合的.
下面举两个典型的例子,可以使用上述规则来进行类型判断.
int *risk[10]; // risk是一个数组,大小为10,存储的是指向int型的指针.
int (*risk)[10]; // risk是一个指针,指向的类型为大小为10的存储int型数据的数组.
下面的例子是与typedef一起使用的情况
typedef int arr5[5];
typedef arr5 * p_arr5;
typedef p_arr5 arrp10[10];
arr5 togs; // togs是一个具有5个int型数据的数组.
p_arr5 p2; // p2是一个指针,指向的类型为大小为5的存储int型数据的数组.
arrp10 ap; // ap是一个数组,大小为10,存储的类型为 指向大小为5的存储int类型数据的数组的指针.
函数指针
函数指针类型通过返回值与参数类型来进行彼此间的区别.使用函数指针只需要记住一点即
可,如果想使用一个类型的函数指针,首先声明一个该类型的函数,然后用(*typename)形式的
表达式代表函数名.typename就成为可指向那种类型函数的指针了.
int demo(int a)
{
return a;
}
int main()
{
int iNum = 1;
int (*func_var)(int a); //函数指针声明
func_var = demo; //函数指针赋值
// 下面是两种使用函数指针的方法 实际上是等价的.
func_var(iNum);
(*func_var)(iNum);
// 下面是与typedef的结合使用;
typedef int (*func_type)(int a); // 指针类型声明
func_type demo_func_type;
demo_func_type = demo;
demo_func_type(iNum);
(*demo_func_type)(iNum);
}
只要理解好上面的例子,就可以基本熟练的使用函数指针了.