剖析c语言结构体的高级用法(一)
前言
在写这篇文章之前,说实话,自身对结构体的用法,只会两点——就是点访问式和指针式访问结构体内部成员。这对一个搞底层的工程师来讲,显然实在太low了。不妨读者看到这里,可以停下来思索一下,看看自己对c语言结构体掌握了多少。下面是我这几天结合自己的学习而总结的一篇算比较全的关于结构体的用法,欢迎大家来吐槽。
其实在之前的文章里面,我已经有说为啥在c语言里面要引入结构体这一概念——,这里的话,我就不再废话了,直接来点实际的。
一、结构体的各种使用方法(很全):
-
这里的话,我以实际例子直接开干,就不过多的介绍一些非常基础的东西(有没看明白的读者可以上网查)。
1# include <stdio.h>
2# include <stdlib.h>
3
4struct Student {
5 char name[20];
6 float fScore[3];
7}student = {"dire",98.5,89.0,93.5}; //初始化结构体变量
8
9
10void Display(struct Student *pStruct)
11{
12 printf("------Information-------\n");
13 printf("Name:%s\n",pStruct->name);
14 printf("Chinese:%.2f\n",(*pStruct).fScore[0]);
15 printf("Math:%.2f\n",(*pStruct).fScore[1]);
16 printf("English:%.2f\n",pStruct->fScore[2]);
17}
18
19
20int main ()
21{
22 Display(&student); //将结构体变量的首地址作为实参传入pStruct指针变量中
23
24 return 0;
25}
说明:
b、再来看一个示例(结构体变量做形参):
1 #include <stdio.h>
2 typedef struct A{
3 int a;
4 }s;
5 void fun(s b)
6 {
7 b.a=99;
8 printf("the b.a is %d\n",b.a);
9 }
10 int main(void)
11 {
12 s c; //这里的s等价于struct A
13 c.a=8;
14 printf("the c.a is %d\n",c.a);
15
16 fun(c);
17
18 return 0;
19 }
演示结果:
说明:
2、结构体数组的几种使用形式:
a、结构体数组示例:
1 #include <stdio.h>
2 struct{
3 char *name; //姓名
4 int num; //学号
5 int age; //年龄
6 char group; //所在小组
7 float score; //成绩
8 }class[5] = {
9 {"Li ping", 5, 18, 'C', 145.0},
10 {"Zhang ping", 4, 19, 'A', 130.5},
11 {"He fang", 1, 18, 'A', 148.5},
12 {"Cheng ling", 2, 17, 'F', 139.0},
13 {"Wang ming", 3, 17, 'B', 144.5}
14};
15int main()
16{
17 int i, num_140 = 0;
18 float sum = 0;
19 for(i=0; i<5; i++)
20 {
21 sum += class[i].score;
22 if(class[i].score < 140) num_140++;
23 }
24 printf("sum=%.2f\naverage=%.2f\nnum_140=%d\n", sum, sum/5, num_140);
25 return 0;
26 }
演示结果:
说明:
上面的结构体数组class[5]相当于数组里面的每个一个元素是一个结构体。
b、结构体指针数组:
1 #include <stdio.h>
2 typedef struct A{
3 int a;
4 }s,*st;
5 int main(void)
6 {
7 s stu1,stu2;
8 st array[2];
9 stu1.a=2;
10 stu2.a=3;
11 array[0]=&stu1;
12 array[1]=&stu2;
13 printf("thearray[0]=%d,array[1]=%d\n",array[0]- >a,array[1]->a);
14
15 return 0;
16 }
演示结果:
说明:
1 #include <stdio.h>
2 struct R{
3int a;
4int b;
5char *name;
6}s[3]={{2,4,"like"},{3,5,"like"},{2,4,"like"}};
7int main(void)
8{
9 struct R (*array)[3];
10 array=&s;
11 printf("the array->b is %d\n",array[0]->a);
12
13return 0;
14 }
c、结构体里面嵌套结构体数组(这里就顺便也讲了结构体嵌套的知识点了):
结构体嵌套的问题有哪些?
----结构体的自引用,就是在结构体内部,包含指向自身类型结构体的指针。
----结构体的相互引用,就是说在多个结构体中,都包含指向其他结构体的指针
结构体应该注意的问题?
----结构体定义中可以嵌套其他结构体类型的变量,不可以嵌套自己这个类型的变量。
1 #include<stdio.h>
2 struct E {
3 int a;
4 };
5 struct D{
6 struct D a; //A是一个结构体,A的内部还会有一个结构体,
7 //以此下>去,无线循环(类似于递归函数)。在内存分配的时候,由于无限的嵌套,无法确定结构体的长度,所>以时非法的。
8 struct E b;
9 int value;
10};
11int main()
12{
13 return 0;
14}
演示结果:
----可以嵌套自己类型的指针。
1 #include<stdio.h>
2 struct E {
3 int a;
4 };
5 struct D{
6
7 struct D *c;
8 struct E b;
9 int value;
10};
11int main()
12{
13 return 0;
14}
说明:
由于指针的长度时确定的(在32位机器上指针长度是4),所以编译器能够确定该
结构体的长度。
这个指针看似指向自身,其实不是,而是执行同一类型的不同结构。
综合应用:
1#include <stdio.h>
2 struct A{
3int year;
4int month;
5int day;
6 };
7
8 struct B{
9 long int num;
10 struct A a;
11 // struct A *b;
12 struct A array[3];
13 char *name;
14}s1={200,{1998,2,3},{{1999,3,4},{1999,5,6},
15 {1999,7,8}},"wangwu"};
16
17 int main(void)
18 {
19 struct B s2;
20 s2=s1;
21 printf("%ld %s %d\n",s2.num,s2.name,sizeof(int));
22printf("year:%d,month:%d,day:%d\n",s2.a.year,s2.a.month,s2.a.day);
23printf("year:%d,month:%d,day:%d\n",s2.array[0].year,s2.array[0].month,s2.array[0].day);
24printf("year:%d,month:%d,day:%d\n",s2.array[1].year,s2.array[1].month,s2.array[1].day);
25printf("year:%d,month:%d,day:%d\n",s2.array[2].year,s2.array[2].month,s2.array[2].day);
26 return 0;
27 }
演示结果:
说明:
在这里我们可以看到,结构体之间是可以进行赋值的,就比如s2=s1,这样就可以用结构体变量s2来继续访问结构体里面的各个成员(可以达到同样的效果的)。这里在结构体里面嵌套了结构体变量和结构体数组,用法和不嵌套的时候是一样的。下面我们关键来讲一下这个结构体里面嵌套结构体指针,该怎样来操作呢,这是要讲的重点了(读者看到这里也可以先想想该如何进行操作):
1 #include <stdio.h>
2 struct B{
3 long int num;
4 struct B*b;
5 }s1={200,0};
6
7 int main(void)
8 {
9struct B s2={200,&s1
10};
11
12 printf("the s2.num=%ld\n",s2.num);
13 printf("(*(s2.b)).num=%ld\n",(*(s2.b)).num);
14
15return 0;
16 }
演示结果:
说明:
1 #include<stdio.h>
2 struct s1
3 {
4 float a;
5 struct
6 {
7 int ba;
8 int bb;
9
10 struct
11 {
12 int bca;
13 int (*bcb)[3];//数组指针
14 } *bc;
15 } b;
16 };
17int main( void )
18{
19int a[3]={3};
20struct
21{
22 int bca;
23 int (*bcb)[3];
24}bc=
25{
26 3,
27 &a
28};
29
30struct s1 s=
31{
32 3.14,
33 {
34 1,
35 2,
36 ( void* )&bc
37 }
38};
39 struct s1 *p=&s;
40 printf("%d\n",*(p->b.bc->bcb)[0]);
41 return 0;
42 }
演示结果:
3、结构体函数指针:
1 #include <stdio.h>
2 #include <stdlib.h>
3 struct A{
4int(*add)(int a,int b);//函数指针
5int(*sub)(int a,int b);
6int(*mult)(int a,int b);
7 };
8 int test_add(int a,int b)
9 {
10 return (a+b);
11 }
12 int test_sub(int a,int b)
13 {
14 return (a-b);
15 }
16 int test_mult(int a,int b)
17 {
18 return (a*b);
19 }
20 void print_usage()
21 {
22 printf("打印用法\n");
23 }
24 int main(int argc,char **argv)
25 {
26 struct A s={
27 .add=test_add,
28 .sub=test_sub,
29 .mult=test_mult,
30 };
31 int a=9,b=3;
32 printf("a+b=%d\n",s.add(a,b));
33 printf("a-b=%d\n",s.sub(a,b));
34 printf("a*b=%d\n",s.mult(a,b));
35
36 return 0;
37 }
演示结果:
说明:
用法还是和函数指针的用法一样,区别不大。
二、总结:
上面汇总了一些结构体的高级用法,有些不怎么常见,但是开阔一些眼界还是有的,哈哈。