C/C++心得-结构体
先說句題外話,個人認為,基本上所有的高級語言被設計出來的最終目的是降低軟件開發難度,提升軟件開發人員素質和團隊協作能力,降低軟件維護的難度。在學習語言的時候,可以從這么方面來推測各種語言語法設計的原因,從來更好的掌握各種編程語言。
總結一下C語言中的數據類型結構:
1.常用基本數據類型(int, char, float, double, short, long等等)
2.數組
3.指針
4.枚舉
5.結構體
6.公用體
...
這其中除了共用體不常用外,其他都是實際開發中經常用到的數據結構。其他的之前兩篇都有說明,今天來說說枚舉和結構體。
(初學者應該養成讀代碼從main開始讀的習慣)
1.枚舉
枚舉作為一種數據類型,用于聲明一組命名的常數,用來說明一種事物的不同類型或屬性。實際應用作用的話,個人認為是提高代碼的可讀性,減小程序的維護難度。
舉個例子,一個程序中需要使用變量表示顏色,那么寫程序前我們需要先設定標準:0表示白色,1表示紅色,2表示黃色,3表示藍色...,那么程序代碼如下:
1 #include <stdio.h> 2 #include <stdlib.h> 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 <stdio.h> 2 #include <stdlib.h> 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 <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 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 <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 typedef enum _Sex 7 { 8 Male, 9 Female 10 }Sex; 11 12 struct Student 13 { 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 <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 enum Sex 7 { 8 Male, 9 Female 10 }; 11 12 typedef struct _Student 13 { 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的定義方式,主要是省去一個struct 23 24 return 0; 25 }typedef的用法,先正常定義,然后用別名替代掉原變量(或函數名)名稱的位置,如:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 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替換為 * name 10 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 <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 struct Student1 7 { 8 int num; 9 char name[32]; 10 short sex; 11 }; 12 struct Student2 13 { 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:8 long:48,int:40 stu1: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 <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 enum Sex 7 { 8 Male, 9 Female 10 }; 11 12 struct Student1 13 { 14 int num; 15 char name[32]; 16 short sex; 17 }; 18 struct Student2 19 { 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的首地址,將其賦給stu1Name 38 stu2Name = (char *)(((char *)&stu2) + 8); // 取stu2的地址,向后偏移8位,這個地址就是name的首地址,將其賦給stu2Name 39 40 printf("stu1:%s,stu2:%s\n", stu1Name, stu2Name); // 打印出值 41 getchar(); 42 return 0; 43 }以上代碼執行結構為:
int:4, char:1, short:2, longlong:8 long:56,int:40 stu1:107fdb0,stu2:107fd70 stu1:107fe50,stu2:107ff30 stu1:LiLei,stu2:WaLiu這說明可以通過地址偏移的方式取得結構體變量內部的值。
轉載于:https://www.cnblogs.com/yaoh/p/4396866.html
總結
以上是生活随笔為你收集整理的C/C++心得-结构体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SqlBulkCopy 批量复制数据到数
- 下一篇: 1)C++对象大小计算