结构
出处:按学科分类—工业技术 企业管理出版社《工程师手册》第862页(3726字)
指针和数组允许将同一类型的数据排列成表以便于程序访问。指针还允许将数组有效地传送给函数并在存贮器中动态分配。当需要处理逻辑上相关的不同数据类型时,使用多个数组就不方便了,虽然有必要分开处理各种数据类型,但常常希望将相关数据类型作为一个整体。C语言的结构允许将任意一个标准数据类型结合在一起定义新的数据类型。一旦定义了结构中的数据类型及大小,结构就可以象C的其它数据类型一样使用。结构数组,指向结构的指针,以及包含其它的结构的结构都可以进行定义。
用户定义结构的一个缺点是,C的标准操作符不适用于这一新的数据类型。虽然C的超集C++语言允许用户定义结构操作符(参看B.Stroustrup的The C++Programining Langnage一书),但C语言不支持以上概念,因此通常定义函数或宏来处理用户定义的结构。
1.结构的声明与引用
结构是通过结构摸板定义的。模板中指明了每个元素的类型以及引用该元素的名称,所有元素排列在一对大括号内,有N个元素的结构,其一般形式为
struct tag_name{
type1 element_name1;
type2 element_name2;
…
typeN element_nameN;
}variable_name;
其中type1,type2,……typeN代表C的有效数据类型(char,int,float,double,不带存贮类描述符),element-namel,element-name2,……element-nameN代表结构中各元素的名称,tag-name是用来引用结构的可选名称,可选的variable-name定义结构变量的名字。下述名为record的结构模板定义了一个由一个名为length的整数,一个名为sample-rate的浮点数,一个名为name字符指针和一个名为data的整数指针构成有结构:
strut record{
int length;
float sample-rate;
char*name;
int*data;
};
利用这个模板可以声明一个名为voice的结构:
struct record voice;
类型为record的结构voice可以初始化为:
voice length=1000;
voice.sample-rate=10.13;
voice.name=“voice signal”;
该结构的最后一个元素是一整数指针,应指向含1000个元素的整数组的开始位置。结构中每个元素均以structure-name.element-name的形式引用。因此,voice结构中的1000个元素的数组可以分配如下:
voice.data=(int*)calloc(1000,sizeof(int));
类似地,该结构的另外三个元素可以用下述代码进行显示:
printf(“\nLength=%d”,voice.length);
printf(“\nSampling rate=%f”,voice.sample-rate);
printf(“\nRecord name=%s”,voice.name);
对结构使用typedef语句可得到用户定义的类型,并使结构声明更简单。typedef为结构数据类型定义新的名字。它比#define功能更强,因为typedef是编译器指令,而不是预处理器指令。我们可以将record结构取名为RECORD:
typedefstruct record RECORD;
上述语句的实质作用是,程序出现的所有RECORD都被替换成record结构的定义。因此,定义voice结构可以非常简单:RECORD voice;.
typedef语句和结构的定义可以结合在一起,从而可以去掉名称record:
typedef struct{
int length;
float sample-rate;
char*name;
int*data
}RECORD;
实际上,用typedef语句可以为任意数据类型(包括指针数组,指针数组以及另一typedef)定义新的名字。例如,语句
typedef char STRING[80];
使得定义80个字符的数组非常简单:STRING namel,name2,该缩写形式完全等价于charname1[80],name2[80];.
2.结构指针
利用结构指针可以动态分配结构数组,或在函内有效地访问结构。以结构类型RECORD为例,下述代码段给一个长度为5的RECORD结构的数组动态地分析空间:
RECORD*voices
voice=(RECORD*)calloc(5,sizeof(RECORD));
这两个语句等价于数组定义RECORD voice[5];,只是由calloc分配的存贮块还可以由函数free释放。不论哪种定义,数组中每个元素的长度可打印如下:
int i:
for(i=0;i<5;i++)
printf(“\nLength of voice%d”=%d,i,voices[i],length);
数组voice也可通过指向结构数组的指针进行访问。设voice-ptr为RECORD指针(用语句RECORD*voice-ptr声明);则(voice-ptr).length表示voice-ptr所指RECORD的长度。由于这种形式的指针操作在C语言经常出现。C定义了一个特殊操作符->.因此voice-ptr-〉length等价于(*voice-ptr).length.这一缩写形式与函数一起使用时尤为方便,因为传送给函数参数是结构指针的本地拷贝。例如,以一函数打印长为size的RECORD数组中每个记录的长度:
因此,调用以上函数和语句如print-record-length(voices,5);将打印长度为5的RECORD结构数组中每个元素的长度存贮。