11.2 结构体类型、结构体变量的定义和引用
考点2 结构体类型的变量、数组和指针变量的定义
真考链接
考点2属于重点理解、重点掌握内容。在选择题中的考核概率为20%。此知识点常常会结合其他知识点进行综合考查,考核方式多以选择题的形式出现。
一共有4种方式定义结构体类型的变量、数组和指针变量。
(1)紧跟在结构体类型说明之后进行定义。
例如:
struct student
{ char name[12];
char sex;
int num;
}std,array[10],*p;
此处,在说明结构体类型structstudent的同时,定义了一个结构体变量std、具有10个元素的结构体数组array和基类型为结构体类型的指针变量p。
具有这一结构类型的变量中只能存放一组数据(即一个学生的记录)。结构体变量中的各成员在内存中的存储是按说明中的顺序依次排列的。
如果要存放多个学生的数据,就要使用结构体类型的数组。以上定义的数组array就可以存放10名学生的档案。此时首先是作为数组,它的每一个元素都是一个structstudent类型的变量,所以仍然符合数组元素属同一数据类型这一原则。
以上定义的指针变量p可以指向具有structstudent类型的存储单元,但目前还没有具体的指向。
(2)在说明一个无名结构体类型的同时直接进行定义。
例如:以上定义的结构体中可以把student略去,写成:
struct
{
…
}std,array[10],*p;
这种方式与前一种的区别仅仅是省去了结构体标识名。通常用在不需要再次定义此类型结构变量的情况。
(3)先说明结构体类型,再单独进行变量定义。
例如:
struct student{
…
};
structstudent std,array[10],*p;
此处先说明了结构体类型structstudent,再由一条单独的语句定义了变量std、数组array和指针变量p。
(4)使用typedef说明一个结构体类型名,再用新类型名来定义变量。
例如:
typedef struct
{ char name[I2]:
char sex;
int num;
}ST
ST std,array[10],*p;
此时,ST是一个具体的结构体类型名,它能够唯一地标识这种结构体类型。因此,可以直接用它来定义变量,如同使用int等基本类型一样,此时是不能写关键字struct的。
小提示
对于某个具体的结构体类型,成员的数量必须固定,这一点与数组相同;但该结构体中各个成员的类型可以不同,这是结构体与数组的重要区别。
不能只使用struct而不写结构体标识名student,因为struct不像int、char可以唯一地标识一种数据类型。作为构造类型,属于struct类型的结构体可以有任意多种具体的“模式”,因此,struct必须与结构体标识名共同来说明不同的结构体类型;也不能只写结构体标识名student而省掉struct。因为student不是类型标识符,只有关键字struct和student一起才能唯一地确定以上所说明的结构体类型。
常见问题
类型和变量有什么区别?
类型和变量是两个不同的概念,使用时应注意区别。只能对变量赋值、存取和运算,而不能对一个类型进行赋值、存取或运算。可以单独使用结构体中的成员,它与普通变量的作用相同。
真题精选
【例1】以下程序的运行结果是( )。
#include "stdio.h"
main()
{ struct date {
int year,month,day;
}today;
printf("% d\n",sizeof(struct date));
}
A.6 B.8 C.10 D.12
【答案】A
【解析】结构体变量的长度是其内部成员总长度之和,本题中,structdate中包含year、month、day这3个整型变量。一个整型变量所占的字节数为2。注意结构体和共用体的差别,这是本题容易混淆的地方。
【例2】若有以下结构体定义:
struct example {
int x;
int y;
}v1;
则( )是正确的引用或定义。
A.example.x=10; B.examplev2; v2.x=10;
C.structv2; v2.x=10; D.structexamplev2={10};
【答案】D
【解析】此题考查基本的结构体定义和引用方法。选项A的错误是通过结构体名引用结构体成员,选项B的错误是将结构体名作为类型名使用,选项C的错误是将关键字struct作为类型名使用,选项D是定义变量v2并对其初始化的语句,初始值只有前一部分,这是允许的。
【例3】有以下程序:
#include <stdio.h>
main()
{ struct cmplx{int x;int y;}cnum[2] ={1,3,2,7 };
printf("% d\n",cnum[0].y/cnum[0].x*cnum[1].x);
}
则正确的输出结果为( )。
A.0 B.1 C.3 D.6
【答案】 D
【解析】程序定义了一个名为cnum的含有两个元素的结构体类型数组,结构体类型为structcmplx,cnum的每个元素含有两个成员。在定义cnum的同时给它的元素赋初值,cnum[0].x的初值是1,cnum[0].y的初值是3,cnum[1].x的初值是2,cnum[1].y的初值是7。因此,printf输出项中的表达式可代入为3/1*2,输出结果是6。总结:对结构体变量(或数组)赋初值时,C编译程序按每个成员在内存中排列的顺序,一一对应赋予初值表中的值。
【例4】设有以下定义:
struct sk
{ int a;
float b;
}data;
int *p;
若要使p指向data中的a域,正确的赋值语句是( )。
A.p=&a; B.p=data.a; C.p=&data.a; D.*p=data.a;
【答案】C
【解析】结构体变量的引用方法有3种:①结构体变量名.成员名;②指针变量名->成员名;③(*指针变量名).成员名。因为p是指针变量,所以应将地址值赋给p。
【例5】某学生的记录由学号、8门课程成绩和平均分组成,学号和8门课程的成绩已在主函数中给出,请编写函数fun(),其功能是:求出该学生的平均分,并放入记录的ave成员中。
例如,学生的成绩是85.5、76、69.5、85、91、72、64.5、87.5,则他的平均分应为78.875。
注意:部分源程序给出如下。
请勿改动主函数main()和其他函数中的任何内容,仅在函数fun()的花括号中填入你编写的若干语句。
试题程序
#include <stdio.h>
#define N 8
typedef struct {
char num[10];
double s[N];
double ave;
}STREC;
void fun(STREC *a)
{
}
void main()
{ STREC s ={"GA005 ",85.5,76,69.5,85,91,72,64.5,87.5};
int i;
fun(&s);
printf("The % s's student data:\n",s. num);
for(i=0;i<N;i++)
printf("% 4.1f\n",s.s[i]);
printf("\nave=% 7.3f\n",s.ave);
}
【答案】void fun(STREC *a)
{ int i;
a->ave=0.0;
for(i=0;i<N;i++)
a->ave=a->ave+a->s[i];
/*求各门课程成绩的总和*/
a->ave=a->ave/N;/*求平均分*/
}
【解析】本题考查:结构体类型成员运算,指向结构体类型的指针变量作函数参数。本题考查自定义形参的相关知识点,程序流程是这样的:在fun()函数中求出平均分后,返回到主函数时平均分也要代回,所以只能定义一个指针类型的形参STREC*a,此时,引用成员的方式可以使用指向运算符,即a->ave和a->s[i],当然也可用(*a).ave和(*a).s[i]。