C结构的应用
C结构的应用中,常用到的有:结构数组、结构嵌套、指向结构的指针、向函数传递结构信息、C99标准的复合文字和结构、结构内容在文件中的存储等。
下面我将分别简述这几个方面,由于最近上课的时间太多了,偶然有空来更新下,可能会有点散乱:
一、结构数组
结构数组和一般的数组没有太大的区别,主要分别一点:一个结构实际上就是一种新的数据类型。在结构数组中的每个元素也就是一种结构数据类型。声明也和其它的数组一样的。如:
struct book{
char title[100];
char author[50];
float value;
}
struct book library[100];
使用如下面所示:
printf("%s",library[0].title);
结构名后面同样用点运算符,点运算符后面跟上成员名。
从上面可以看出它和数组的关系,每一个数组元素就是一个结构体。但是如果用一个大的结构数组就可能造成堆栈溢出使用时一定要小心!可以把数组设为静态的或外部的,或者将数组大小减小。
二、结构嵌套
在一些数据处理和字符处理中,在一个结构中嵌套一个结构有时会显得更加的方便。首先,注意结构声明中是如何创建嵌套结构的。看下面的例子:
struct names { //这是第一个结构
char first_name[100];
char second_name[100];
int num;
};
struct guy { //第二个结构
strtuct names handle; //结构的嵌套
float tall;
char job[100];
};
从上面的形式可以清楚的看到嵌套结构的定义。即:在一个结构定义在另一个结构(暂且叫做:内部结构)中,内部结构就是外部结构中的一个成员。现在看来这样的一个结构就显得十分的复杂了。这样也就形成了一种复杂的数据类型。
那么嵌套结构要如何访问呢? 对嵌套结构的成员进行访问;只需使用两次点运算符。如:
struct guy study {
{"Xue","Yang",100}, //这里是对内部结构进行初始化。
//注意结构初始化时,各个成员之间用逗号分隔。
169.0,
"Student"
};
printf("hello ,%s!\n",study.handle.first_name);
上面的最后一个printf()函数中的study.handle.first_name,这个语句可从左到右的解释: (study.handle).first_name
即:先找到study,然后找到study的成员handle,再找到handle的成员first_name。
三、指向结构的指针
在这之前先说说指针的好处。不管做什么,先要明白做这个是为了什么嘛!呵呵
第一,就像指向数组的指针比数组本身更容易操作一样,指向结构的指针通常都比结构本身更容易操作。
第二,在一些早期的C实现中,结构不能作为参数被传递给函数,但指向结构的指针可以。
第三,许多奇妙的数据表示都使用了包含指向其他结构的指针的结构。
对于程序上的使用,用例子来解释应该是最好的。例如下面的程序:
struct names { //定义一个结构
char first_name[];
char second_name[];
int num;
};
//声明一个结构指针:
struct names * pnames; //这样的一个指针和其它的指针其实也没有什么区别,仅仅只是它的数据类型为:struct names *
//再在这里声明一个结构数组
struct names names_array[2];
//对进行赋值结构指针
pnames = &names_array[0]; //pnames 指向数组names_array的第一个元素。
那么完成这样的定义、声明和赋值之后要如何对用这个结构指针对它所指向的结构中的成员进行访问呢?
我们在用到结构指针时会用到一种就的运算符 ->
形如:pnames->first_name访问结构当中first_name成员。也可以用别外一种写法达到同样的作用,如:(*pnames).first_name 。这两种不同的写法访问的是同一个结构数组中的同一个成员。使用指针的好处就是可以实现一些复杂的数据组成形式的灵活运用,如:用链表实现队列、二叉树。
向函数传递结构信息
因为结构实际上是表示的一种数据类型,其它常用的数据类型都可以做为行参和返回值在函数之间传递,那么结构作为一种数据类型,同样可以有这样的传递。如下所示:
struct names { //定义一个结构
char first_name[];
char second_name[];
int num;
};
struct names num_1;
.......
void func_0(struct names p);
void func_1(){
struct names num_0;
func_0(num_1);
....
}
但是在程序中很我用到把整个结构进行传递的,因为C语言的子函数的完全包含,每一个子函数调用的时都要分配大量的空间,这样会造成严重的浪费。所以一般都要是用指针进行传递。 如下所示:
func_0(struct names * p);
void func_1(){
struct names * num_0 = NULL;
func_0(num_0);
....
}
C99的复合文字
用过数组的复合文字,就会很清楚复合文字其实也就是一种常量。数组的复合文字没有数组名,而结构的复合文字也同样的理解它。即结构不会声明一个结构名,而只有结构中的成员。
如:
(char [4]){3,2,4,9}; //数组
(struct names ){"hello","so good",100};//结构
以上的形式是有那么一点点的奇怪,但是对于新鲜事物的认知可以让你更加了解它。它们主要是只有一个数据类型,而没有数组/结构名。那么我们在自已的代码中如何使用它们呢?
一:它可以作为上层函数和下层函数之间的参数传递。如果你的函数参数是一个结构,你可以复合文字作为一个实际的参数传递。
二:你的复合文字的地址和其它的结构或者数组是一样的,你可以把它们的地址进行传递。它们的存储和其它的同类型数据一样只是没有个数组名和结构名而已,所以复合文字也可以指定初始化一个成员变量。声明在函数外面的为静态存储,声明在函数里面的为自动存储(函数调用时是对数据放入堆栈中,调用完成后再全部清出栈。即:C中的子函数可以全包含在外部函数中)。
数组(复合文字)也是一样,常常把它的赋给一个指针,即:用指针保存其首地址。让程序更用的灵活!
结构在文件中的存储
先解释两个专业名词:记录,一个结构中保存的整套信息。字段,单个的项目。