博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C/C++心得-结构体
阅读量:4639 次
发布时间:2019-06-09

本文共 7968 字,大约阅读时间需要 26 分钟。

先说句题外话,个人认为,基本上所有的高级语言被设计出来的最终目的是降低软件开发难度,提升软件开发人员素质和团队协作能力,降低软件维护的难度。在学习语言的时候,可以从这么方面来推测各种语言语法设计的原因,从来更好的掌握各种编程语言。

总结一下C语言中的数据类型结构:

1.常用基本数据类型(int, char, float, double, short, long等等)

2.数组

3.指针

4.枚举

5.结构体

6.公用体

...

这其中除了共用体不常用外,其他都是实际开发中经常用到的数据结构。其他的之前两篇都有说明,今天来说说枚举和结构体。

(初学者应该养成读代码从main开始读的习惯)

1.枚举

枚举作为一种数据类型,用于声明一组命名的常数,用来说明一种事物的不同类型或属性。实际应用作用的话,个人认为是提高代码的可读性,减小程序的维护难度。

举个例子,一个程序中需要使用变量表示颜色,那么写程序前我们需要先设定标准:0表示白色,1表示红色,2表示黄色,3表示蓝色...,那么程序代码如下:

1 #include 
2 #include
3 4 void printColor(int color) 5 { 6 switch (color) 7 { 8 case 0: 9 printf("白色\n");10 break;11 case 1:12 printf("红色\n");13 break;14 case 2 :15 printf("黄色\n");16 break;17 case 3:18 printf("蓝色\n");19 break;20 default:21 break;22 }23 }24 25 int main(int arg, char *args)26 {27 int color0 = 0; // 白色28 int color1 = 1; // 红色29 int color2 = 2; // 黄色30 int color3 = 3; // 蓝色31 32 printColor(color0);33 printColor(color1);34 printColor(color2);35 printColor(color3);36 37 getchar();38 return 0;39 }

(关于枚举的例子只是作为说明,这些作为例子有些不太好)如果程序代码量很大的情况下,0,1,2,3的这种数字意义很容易忘记,这时可以用到枚举

1 #include 
2 #include
3 4 enum Color 5 { 6 White, // 白色 7 Red, // 红色 8 Yellow,// 黄色 9 Blue // 蓝色10 };11 12 void printColor(int color)13 {14 switch (color)15 {16 case White:17 printf("白色\n");18 break;19 case Red:20 printf("红色\n");21 break;22 case Yellow:23 printf("黄色\n");24 break;25 case Blue:26 printf("蓝色\n");27 break;28 default:29 break;30 }31 }32 int main(int arg, char *args)33 {34 int color0 = White; // 白色35 int color1 = Red; // 红色36 int color2 = Yellow; // 黄色37 int color3 = Blue; // 蓝色38 39 printColor(color0);40 printColor(color1);41 printColor(color2);42 printColor(color3);43 44 getchar();45 return 0;46 }

对枚举的理解应用暂时就如此,关于枚举的作为属性应用,以及其他方面的应用,有兴趣的可以查查其他资料。

2.结构体

结构体的意义之一同样是增加代码可读性。而且结构体配合指针使得C语言变得非常灵活。

结构体是由一系列具有相同或不同类型的数据组成。

 下面用两种方法定义并输出一个学生的信息。

首先是不用结构体和枚举的方法

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 int getSex(short sex, char * sexVal) 7 { 8 if (sexVal == NULL) 9 {10 return -1;11 }12 switch (sex)13 {14 case 0:15 strcpy(sexVal, "男");16 break;17 case 1:18 strcpy(sexVal, "女");19 break;20 default:21 return -2;22 break;23 }24 return 0;25 }26 // 不用结构体和枚举的方法27 int main(int arg, char * args[])28 {29 int num = 1;30 char name[32] = "LiLei";31 short sexN = 0;32 char sex[4] = { '\0' };33 if (getSex(sexN, sex) != 0)34 {35 return -1;36 }37 printf("学号:%d,姓名:%s,性别:%s\n", num, name, sex);38 39 getchar();40 return 0;41 }

下面使用结构体和枚举改造代码:

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 typedef enum _Sex 7 { 8 Male, 9 Female10 }Sex;11 12 struct Student13 {14 int num;15 char name[32];16 short sex;17 };18 19 int getSex(Sex sex, char * sexVal)20 {21 if (sexVal == NULL)22 {23 return -1;24 }25 switch (sex)26 {27 case Male:28 strcpy(sexVal, "男");29 break;30 case Female:31 strcpy(sexVal, "女");32 break;33 default:34 return -2;35 break;36 }37 return 0;38 }39 40 int main(int arg, char * args[])41 {42 struct Student stu = { 1, "LiLei", Male };43 char sex[4] = { 0 };44 if (getSex(stu.sex, sex) != 0)45 {46 return -1;47 }48 printf("学号:%d,姓名:%s,性别:%s\n", stu.num, stu.name, sex);49 getchar();50 return 0;51 }

 

可以发现,在没有什么注释的情况下,从Main开始读代码,第二段代码是比较好理解。

使用结构体一般都会使用typedef给结构体起个别名,当然typedef在指针、数组等方面都有应用,使用typedef可以精简代码。下面举个例子

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 enum Sex 7 { 8 Male, 9 Female10 };11 12 typedef struct _Student13 {14 long num;15 char name[32];16 short sex;17 } Student; // 使用typedef给结构体起别名18 19 int main(int arg, char * args[])20 {21 struct _Student stu1 = { 50, "hel", Male }; // 不使用typedef前的定义方式22 Student stu2 = { 100, "yao", Male }; // 使用typedef的定义方式,主要是省去一个struct23 24 return 0;25 }

typedef的用法,先正常定义,然后用别名替代掉原变量(或函数名)名称的位置,如:

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 typedef int mI; 7 typedef char mCh; 8 typedef char mStr[32];// 原来定义char数组是 char * str[32]; 这里将str替换为别名 9 typedef int (* name)(int a, int b); // int sum(int a, int b), 因为函数需要以指针形式表示,所以把sum替换为 * name10 11 int sum(int a, int b)12 {13 return a + b;14 }15 16 int main(int arg, char *args[])17 {18 mI num = 10;19 mCh ch = 'x';20 mStr str = "hello"; // 这里相当于定义 char str[32] = "hello";21 name func = sum; // 函数指针,相当于 int func(int a, int b); func中的执行代码和sum函数相同22 printf("num:%d,a=%c,str=%s,func(1, 2)=%d\n", num, ch, str, func(15, 20));23 getchar();24 return 0;25 }

再说说结构体的长度。结构体的长度要略大于或等于其内部成员的总长度。主要是为了程序速度,在一个结构体内有多个类型的成员的时候,会做一些“对齐”处理,该处理有可能导致结构体变量占用空间变大。

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 struct Student1 7 { 8 int num; 9 char name[32];10 short sex;11 };12 struct Student213 {14 long long num;15 char name[32];16 short sex;17 };18 19 int main(int arg, char * args[])20 {21 struct Student1 stu1;22 struct Student2 stu2;23 printf("int:%d, char:%d, short:%d, longlong:%d\n", sizeof(int), sizeof(char), sizeof(short), sizeof(long long)); // 比较4种数据类型的长度24 printf("long:%d,int:%d\n", sizeof(struct Student2), sizeof(struct Student1)); // 比较两种结构体的长度25 printf("stu1:%x,stu2:%x\n", &stu1, &stu2); // 两个结构体变量的地址26 getchar();27 return 0;28 }

上面这段程序的输出结构为:

int:4, char:1, short:2, longlong:8long:48,int:40stu1:eafeb4,stu2:eafe7c

从第一行输出信息来看,我们可以算出结构体Student1声明的变量(int num, char name[32], short sex)的总长度应该为38,而第二行的实际输出结果为40.

同样可以算出结构体Student2声明的变量(long long num, char name[32], short)的总长度应该为42,而实际结果为48.

一个结构体的长度必定是其内部长度最大基本数据类型元素的整数倍,上面Student1和Student2都符合该项(数组不是基本数据类型)。

而且结构体变量的首地址必定能被其内部长度最大基本数据类型元素整除,如上面eafeb4可以被4整除,eafe7c可以被8整除。

3.结构体的一点高级用法

1.通过地址取结构体内成员的值(代码作为示例,真实开发中应该不会这样写)

1 #define  _CRT_SECURE_NO_WARNINGS 2 #include 
3 #include
4 #include
5 6 enum Sex 7 { 8 Male, 9 Female10 };11 12 struct Student113 {14 int num;15 char name[32];16 short sex;17 };18 struct Student219 {20 long long num;21 char name[39];22 short sex;23 };24 25 int main(int arg, char * args[])26 {27 char * stu1Name = NULL;28 char * stu2Name = NULL;29 struct Student1 stu1 = { 100, "LiLei", Male };30 struct Student2 stu2 = { 100, "WaLiu", Female };31 32 printf("int:%d, char:%d, short:%d, longlong:%d\n", sizeof(int), sizeof(char), sizeof(short), sizeof(long long)); // 比较4种数据类型的长度33 printf("long:%d,int:%d\n", sizeof(struct Student2), sizeof(struct Student1)); // 比较两种结构体的长度34 printf("stu1:%x,stu2:%x\n", &stu1, &stu2); // 两个结构体变量的地址35 printf("stu1:%x,stu2:%x\n", &stu1 + 4, &stu2 + 8);36 37 stu1Name = (char *)(((char *)&stu1) + 4); // 取stu1的地址,向后偏移4位,这个地址就是name的首地址,将其赋给stu1Name38 stu2Name = (char *)(((char *)&stu2) + 8); // 取stu2的地址,向后偏移8位,这个地址就是name的首地址,将其赋给stu2Name39 40 printf("stu1:%s,stu2:%s\n", stu1Name, stu2Name); // 打印出值41 getchar();42 return 0;43 }

以上代码执行结构为:

int:4, char:1, short:2, longlong:8long:56,int:40stu1:107fdb0,stu2:107fd70stu1:107fe50,stu2:107ff30stu1:LiLei,stu2:WaLiu

这说明可以通过地址偏移的方式取得结构体变量内部的值。

转载于:https://www.cnblogs.com/yaoh/p/4396866.html

你可能感兴趣的文章
第二次冲刺 站立会议3
查看>>
LA3029最大子矩阵
查看>>
万网域名MX解析设置方案[net.cn, ubuntu]
查看>>
403. Frog Jump
查看>>
C++学习之二分查找续
查看>>
Vue创建SPA那些事
查看>>
python基础学习1-列表推导式和字典推导式
查看>>
mfc Radio Buttons
查看>>
[JavaScript]父子窗口间参数传递
查看>>
Test Controller Tool
查看>>
86. Partition List
查看>>
[LintCode] 378 Convert Binary Search Tree to Doubly Linked List 解题报告
查看>>
JAVA-初步认识-常用对象API(集合框架-泛型-泛型限定-上限的体现)
查看>>
查找一个字段所处的数据库及表
查看>>
第一周学习进度+四则运算1.0版
查看>>
baba 运动网
查看>>
for循环小练习
查看>>
JAE京东云引擎Git上传管理代码教程和京东云数据库导入导出管理
查看>>
教你如何迅速秒杀掉:99%的海量数据处理面试题
查看>>
高血压吃什么好?
查看>>