嵌入式C语言中结构体详解.docx
- 文档编号:12126793
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:16
- 大小:19.08KB
嵌入式C语言中结构体详解.docx
《嵌入式C语言中结构体详解.docx》由会员分享,可在线阅读,更多相关《嵌入式C语言中结构体详解.docx(16页珍藏版)》请在冰豆网上搜索。
嵌入式C语言中结构体详解
嵌入式C语言中结构体详解
C语言允许用户自己指定这样一种数据结构,它由不同类型的数据组合成一个整体,以便引用,这些组合在一个整体中的数据是互相联系的,这样的数据结构称为结构体,它相当于其它高级语言中记录。
声明一个结构休类型的一般形式如下:
struct结构体名
{成员列表};
结构体名,用作结构体类型的标志,它又称结构体标记,大括号内是该结构体中的各个成员,由它们组成一个结构体,对各成员都应进行类型声明如:
类型名成员名;
也可以把成员列表称为域表,第一个成员也称为结构体中的一个域。
成员名定名规则写变量名同。
structstudent
{
intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
};
定义结构体类型变量的方法
前面只是指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元,为了能在程序中使用结构类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据,可以采取以下3种方法定义结构体类型变量。
(1)先声明结构体类型再定义变量名
如上面已定义了一个结构体类型structstudent,可以用它来定义变量。
如:
structstudent//结构体类型名
student1,student2//结构体变量名
定义了student1,student2为structstudent类型的变量。
在定义了结构体变量后,系统会为之分配内存单元。
例如student1和student2在内存中各占59个字节。
应当注意,将一个变量定义为标准类型(基本数据类型)与定义为结构体类型不同之处在于后者不仅要求指定变量为结构体类型,而且要求指定为某一特定的结构体类型(例如structstudent类型),因为可以定义出许多种具体的结构体类型。
而在定义变量为整形时,只需指定为int型即可。
(2)在声明类型的同时定义变量
例如:
structstudent
{
intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
}student1,student2;
它的作用与第一种方法相同,即定义了两个structstudent类型的变量student1,student2这种形式的定义的一般形式为
struct结构体名
{
成员表列
}变量名表列;
(3)直接定义结构类型变量
其一般形式为
struct
{
成员表列
}变量名表列;
即不出现结构体名。
关于结构体类型,有几点要说明:
a.类型与变量是不同的概念,不是混同,只能对变量赋值,存取或运算,而不能对一个类型赋值,存取或运算。
在编译时,对类型是不分配空间的,只对变量分配空间。
b.对结构体中的成员(即域)可以单元使用,它的作用与地位相当于普通变量,
c.成员也可以是一个结构体变量。
如:
structdate//声明一个结构体类型
{
intmonth;
intday;
intyear;
}
structstudent
{
intnum;
charname[20];
charsex;
intage;
structdatebirthday;
charaddr[30];
}student1,student2;
先声明一个structdate类型,它代表日期包括3个成员month,day,year。
然后在声明structstudent类型时,将成员birthday指定为structdate类型。
d.成员名可以与程序中的变量名相同,二者不代表同一对象。
结构体变量的引用
(1)不能将一个结构体变量作为一个整体进行输入和输出。
只能对结构体变量中的各个成员分别进行输入输出。
引用结构体变量中的成员的方式为
结构体变量名.成员名
例如student1.num表示student1变量中的num成员,即student1的num项,可以对变量的成员赋值。
例如:
student1.num=10010;
"."是成员(分量)运算符,它在所有的运算符中优先级最高,因此可以把student1.num作为一个整体来看待。
上面的赋值语句作用是将整数10010赋给student1变量中的成员num。
(2)如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员。
只能对最低的成员进行赋值或存取以及运算。
例如:
结构体变量student1可以这样访问各成员:
student1.num
student1.birthday.month
注意,不能用student1.birthday来访问student1变量中的成员birthday,因为birthday本身是一个结构体变量。
(3)对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。
student2.score=student1.score;
sum=student1.score+student2.score;
student1.age++;
++student1.age;
由于"."运算符的优先级最高,因此student1.age++是对student1.age进行自加运算。
而不是先对age进行自加运算。
(4)可以引用结构体变量成员的地址。
也可以引用结构体变量的地址。
如:
scanf("%d",&student1.num);//输入student1.num的值
printf("%o",&student1);//输出student1的首地址
但不能用以下语句整体读入结构体变量如:
scanf("%d,%s,%c,%d,%f,%s",&student1);
结构体变量的地址主要用于作函数参数,传递结构体的地址。
结构体变量的初始化
和其它类型变量一样,对结构体变量可以在定义时指定初始值。
如:
#include
structstudent
{
longintnum;
charname[20];
charsex;
charaddr[30];
}a={89031,"LiLin",'M',"123BeijingRoad"};
voidmain()
{
printf("NO.:
%d\nname:
%s\nsex:
%c\naddress:
%s\n",a.num,a.name,a.sex,a.addr);
}
结构体数组
一个结构体变量中可以存放一组数据(如一个学生的学号,姓名,成绩等数据)。
如果有10个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。
结构体数组与以前介绍过的数据值型数组不同之处在于每个数组元素都一个结构体类型的数据,它们分别包括各个成员(分量)项。
5.1定义结构体数组
和定义结构体变量的方法相仿,只需说明其为数组即可。
structstudent
{
intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
};
structstudentstu[3];
以上定义了一个数组stu,其元素为structstudent类型数据,数组有3个元素。
也可以直接定义一个结构体数组。
如:
structstudent
{
intnum;
....
}stu[3];
或
struct
{
intnum;
...
}stu[3];
5.2结构体数组的初始化
与其它类型数组一样,对结构体数组可以初始化如:
structstudent
{
intmum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
}stu[3]={{10101,"LiLin",'M',18,87.5,"103BeijingRoad"},
{10101,"LiLin",'M',18,87.5,"103BeijingRoad"},
{10101,"LiLin",'M',18,87.5,"103BeijingRoad"}};
定义数组stu时,元素个数可以不指定,即写成以下形式:
stu[]={{...},{...},{...}};
编译时,系统会根据给出初值的结构体常量的个数来确定数组元素的个数。
当然,数组的初始化也可以用以下形式:
structstudent
{
intnum;
...
};
structstudentstu[]={{...},{...},{...}};
即先声明结构体类型,然后定义数组为该结构体类型,在定义数组时初始化。
从以上可以看到,结构体数组初始化的一般形式是在定义数组的后面加上:
5.3结构体数组应用举例
下面例子说明结构体数组的定义和引用。
#include
#include
#include
structperson
{
charname[20];
intcount;
}leader[3]={{"Li",0},
{"Zhang",0},
{"Fun",0}};
voidmain()
{
inti,j;
charleader_name[20];
for(i=1;i<=10;i++)
{
scanf("%s",leader_name);
for(j=0;j<3;j++)
if(strcmp(leader_name,leader[j].name)==0)
leader[j].count++;
}
printf("\n");
for(i=0;i<3;i++)
printf("%5s:
%d\n",leader[i].name,leader[i].count);
system("pause");
}
运行结果如下:
LI
Li
Fun
Zhang
Zhang
Fun
Li
Fun
Zhang
Li
Li:
3
Zhang:
3
Fun:
3
指向结构体类型数据的指针
一个结构体变量的指针就是该变量所占据的内存段的起始地址,可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。
指针变量也可以用来指向结构体数组中的元素。
6.1指向结构体变量的指针
指向结构体变量的指针的应用:
#include
#include
#include
structstudent
{
longnum;
charname[20];
charsex;
floatscore;
};
voidmain()
{
structstudentstu_1;
structstudent*p;
p=&stu_1;
stu_1.num=89101;
strcpy(stu_1.name,"LiLin");
stu_1.sex='M';
stu_1.score=89.5;
printf("NO.:
%ld\nname:
%s\nsex:
%c\nscore:
%f\n",stu_1.num,stu_1.name,stu_1.sex,stu_1.score);
printf("NO.:
%ld\nname:
%s\nsex:
%c\nscore:
%f\n",(*p).num,(*p).name,(*p).sex,(*p).score);
system("pause");
}
在主函数中声明了structstudent类型,然后定义了一个structstudent类型的变量,stu_1同时又定义一个指针变量p,它指向一个structstudent类型的数据,在函数的执行部分将结构体变量stu_1的起始地址赋给指针变量p,也就是使p指向stu_1然后对stu_1的各成员赋值,第二个printf函数也是用来输出stu_1各成员的值,但使用的是(*p).num这样的形式,(*p)表示p指向的结构体变量,(*p).num是p指向的结构体变量中的成员num。
注意*p两侧的括弧不可省略,因为成员运算符'.'优先于'*'运算符,*p.num就等价于*(p.num)
运行结果如下:
NO.:
89101
name:
LiLin
sex:
M
score:
89.500000
NO.:
89101
name:
LiLin
sex:
M
score:
89.500000
可以看到两个printf输出的结果相同。
在C语言中,为了使用方便和使之直观,可以把(*p).num改用p->num来代替,它表示*p所指向的结构体变量中的num成员,同样,(*p).name等价于p->name。
也就是说以下三种形式等价:
a.结构体变量.成员名
b.(*p).成员名
c.p->成员名
上面的最后一个printf函数输了项可以改写为
printf("NO.:
%ld\nname:
%s\nsex:
%c\nscore:
%f\n",p->num,p->name,p->sex,p->score);
其中->称为指向运算符。
分析以下几种运算符
p->n得到p指向的结构体变量中的成员n的值
p->n++得到p指向的结构体变量中的成员n的值,用完值后使它加1
++p->n得到p指向的结构体变量中的成员n的值使之加1(先加)
6.2指向结构体数组的`指针
以前介绍过可以使用指向数组或数组元素的指针和指针变量,同样,对结构体数组及其元素也可以用指针变量来指向。
指向结构体数组的指针的应用
#include
#inlcude
structstudent
{
intnum;
charname[20];
charsex;
intage;
};
structstudentstu[3]={{10101,"LiLin",'M',18},
{10102,"ZhangFun",'M',19},
{10103,"WangMin",'F',20}};
voidmain()
{
structstudent*p;
printf("No. name sex age\n");
for(p=stu;p
printf("%5d%-20s%2c%4d\n",p->num,p->name,p->sex,p->age);
system("pause");
}
运行结果如下:
No. name sex age
10101LiLinM 18
10102ZhangFunM 19
10103WangMinF 20
注意以下两点:
(1)如果p的初值为stu,即指向第一个元素,则p+1后指向下一个元素的起始地址。
例如:
(++p)->num先使p自加1,然后得到它指向的元素中的num成员的值(即10102)。
(p++)->num先得到p->num的值(即10101),然后使p自加1,指向stu[1]。
注意以上二者的不同。
(2)程序已定义了指针p为指向structstudent类型数据的变量,它只能指向一个structstudent型的数据(p的值是stu数组的一个元素的起始地址),而不能指向stu数组元素中的某一成员,(即p的地址不能是成员地址)。
例如,下面是不对的:
p=&stu[1].name
编译时将出错。
千万不要认为反正p是存放地址的,可以将任何地址赋给它。
如果地址类型不相同,可以用强制类型转换。
例如:
p=(structstudent*)&stu[1].name;
此时,在p中存放stu[1]元素的name成员的起始地址。
6.3用结构体变量和指向结构体的指针作函数参数
将一个结构体变量的值传递给另一个函数,有3个方法:
(1)用结构体变量的成员作参数,例如:
用stu[1].num或stu[2].name作函数实参,将实参值传给形参。
用法和用普通变量作实参是一样的,属于值传递方式。
应当注意实参与形参的类型保持一致。
(2)用结构体变量作参数。
老版本的C系统不允许用结构体变量作实参,ANSIC取消了这一限制。
但是用结构体变量作实参时,采取的是值传递的方式,将结构体变量所占的内存单元全部顺序传递给形参。
形参也必须是同类型的结构体变量。
在函数调用期间形参也要占用内存单元。
这种传递方式在空间和时间上开销较大,如果结构体的规模很大时,开销是很可观的,此外由于采用值传递方式,如果在执行被调用函数期间改变了形参(也是结构体变量)的值,该值不能返回主调函数,这往往造成使用上的不便。
因此一般较少用这种方法。
(3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。
用结构体变量作函数参数。
#include
#defineFORMAT"%d\n%s\n%f\n%f\n%f\n"
structstudent
{
intnum;
charname[20];
floatscore[3];
};
voidprint(structstudentstu)
{
printf(FORMAT,stu.num,stu.score[0],stu.score[1],stu.score[2]);
printf("\n");
}
voidmain()
{
structstudentstu;
stu.num=12345;
strcpy(stu.name,"LiLi");
stu.score[0]=67.5;
stu.score[1]=89;
stu.score[2]=78.6;
printf(stu);
}
将上面改用指向结构体变量的指针作实参。
#include
#defineFORMAT"%d\n%s\n%f\n%f\n%f\n"
structstudent
{
intnum;
charname[20];
floatscore[3];
}stu={12345,"LiLi",67.5,89,78.6};
voidprint(structstudent*p)
{
printf(FORMAT,p->num,p->name,p->score[0],p->score[1],p->score[2]);
printf("\n");
}
voidmain()
{
print(&stu);
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 语言 结构 详解
![提示](https://static.bdocx.com/images/bang_tan.gif)