嵌入式开发中C语言中结构体解读2016
p = &stu_1;
stu_1.num = 89101;
strcpy(stu_1.name, "Li Lin");
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");
}
在主函数中声明了 struct student 类型,然后定义了一个 struct student 类型的变量,stu_1 同时又定义一个指针变量 p ,它指向一个 struct student 类型的数据,在函数的执行部分将结构体变量 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: Li Lin
sex:M
score:89.500000
NO. :89101
name: Li Lin
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
struct student
{
int num;
char name[20];
char sex;
int age;
};
struct student stu[3] = {{10101, "Li Lin", 'M', 18},
{10102, "Zhang Fun", 'M', 19},
{10103, "Wang Min", 'F', 20}};
void main()
{
struct student *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
10101 Li Lin M 18
10102 Zhang Fun M 19
10103 Wang Min F 20
注意以下两点:
(1)如果 p 的'初值为 stu,即指向第一个元素,则 p + 1 后指向下一个元素的起始地址。例如:
(++p) -> num 先使 p 自加 1 ,然后得到它指向的元素中的 num 成员的值(即10102)。
(p++) ->num 先得到 p->num 的值(即10101),然后使 p 自加 1 ,指向 stu[1]。
注意以上二者的不同。
(2)程序已定义了指针 p 为指向 struct student 类型数据的变量,它只能指向一个 struct student 型的数据(p 的值是 stu 数组的一个元素的起始地址),而不能指向 stu 数组元素中的某一成员,(即 p 的地址不能是成员地址)。例如,下面是不对的:
p = &stu[1].name
编译时将出错。千万不要认为反正 p 是存放地址的,可以将任何地址赋给它。如果地址类型不相同,可以用强制类型转换。例如:
p = (struct student *)&stu[1].name;
此时,在 p 中存放 stu[1] 元素的 name 成员的起始地址。
6.3 用结构体变量和指向结构体的指针作函数参数
将一个结构体变量的值传递给另一个函数,有3个方法:
(1)用结构体变量的成员作参数,例如:用 stu[1].num 或 stu[2].name 作函数实参,将实参值传给形参。用法和用普通变量作实参是一样的,属于 值传递 方式。应当注意实参与形参的类型保持一致。
(2)用结构体变量作参数。老版本的C系统不允许用结构体变量作实参,ANSI C取消了这一限制。但是用结构体变量作实参时,采取的是 值传递 的方式,将结构体变量所占的内存单元全部顺序传递给形参。形参也必须是同类型的结构体变量。在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,如果结构体的规模很大时,开销是很可观的,此外由于采用值传递方式,如果在执行被调用函数期间改变了形参(也是结构体变量)的值,该值不能返回主调函数,这往往造成使用上的不便。因此一般较少用这种方法。
(3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。
用结构体变量作函数参数。
#include
#define FORMAT "%d\n%s\n%f\n%f\n%f\n"
struct student
{
int num;
char name[20];
float score[3];
};
void print(struct student stu)
{
printf(FORMAT, stu.num, stu.score[0], stu.score[1], stu.score[2]);
printf("\n");
}
void main()
{
struct student stu;
stu.num = 12345;
strcpy(stu.name, "Li Li");
stu.score[0] = 67.5;
stu.score[1] = 89;
stu.score[2] = 78.6;
printf(stu);
}
将上面改用指向结构体变量的指针作实参。
#include
#define FORMAT "%d\n%s\n%f\n%f\n%f\n"
struct student
{
int num;
char name[20];
float score[3];
}stu = {12345, "Li Li", 67.5, 89, 78.6};
void print(struct student *p)
{
printf(FORMAT, p->num, p->name, p->score[0], p->score[1], p->score[2]);
printf("\n");
}
void main()
{
print(&stu);
}
【嵌入式开发中C语言中结构体解读2016】相关文章: