網站首頁 編程語言 正文
引言
當前文章介紹動態堆空間內存分配與釋放,C語言結構體定義、初始化、賦值、結構體數組、結構體指針的相關知識點,最后通過一個學生管理系統綜合練習結構體數組的使用。
1. 動態內存管理
C語言代碼----->編譯----->鏈接------>可執行的二進制文件(windows下xxx.exe) 二進制文件中的數據是如何擺放的? 文本數據段、靜態數據段、全局數據段。
堆棧空間: 代碼在運行的時候才有的空間。 棧空間: 系統負責申請,負責釋放。比如: 函數形參變量、數組…… 堆空間: 程序員負責申請,負責釋放。
#include <stdlib.h> //標準庫頭文件 void *malloc(int size); //內存申請。 形參表示申請的空間大小,返回值:申請的空間的地址 void free(void *p); //內存釋放。 形參就是要釋放的空間首地址。
動態空間申請示例。
動態空間申請 #include "stdio.h" #include "string.h" #include <stdlib.h> int main() { int *p=malloc(sizeof(int)); //申請空間 if(p!=NULL) { printf("申請的空間地址: 0x%X\n",p); *p=888; printf("%d\n",*p); } free(p); //釋放空間 return 0; } 示例2: #include "stdio.h" #include "string.h" #include <stdlib.h> ? char *func(void) { char*str=malloc(100); //char str[100]; if(str!=NULL) { strcpy(str,"1234567890"); printf("子函數打印:%s\n",str); //free(str); //釋放空間 return str; } else { return NULL; } } ? int main() { char *p=func(); printf("主函數打印:%s\n",p); return 0; }
2. 結構體
2.1 定義語法
結構體的概念: 可存放不同數據類型的集合。 比如: 存放一個班級學生的信息。 可以使用一個結構體存放一個學生的信息。 一個結構體數組存放整個班級的學習信息。 數組的概念: 可存放相同數據類型的集合。
結構體的定義語法:
//聲明一種新類型-----數據類型 struct <結構體的名稱> { <結構體的成員>1; <結構體的成員>2; ………… }; //最后有分號結束 ? struct MyStruct { char a; int b; float c; char str[100]; };
2.2 定義示例
結構體如何賦值? 如何訪問結構體內部成員
#include "stdio.h" #include "string.h" #include <stdlib.h> ? //定義結構體數據類型 struct MyStruct { char a; int b; float c; char str[100]; }; int main() { struct MyStruct data={'A',123,456.789,"abcd"}; //data就是結構體類型的變量 //結構體變量訪問內部成員的語法: . 點運算符 printf("%c\n",data.a); printf("%d\n",data.b); printf("%f\n",data.c); printf("%s\n",data.str); return 0; }
2.3 初始化
#include "stdio.h" #include "string.h" #include <stdlib.h> ? //定義結構體數據類型 struct MyStruct { char a; int b; float c; char str[100]; }data={'A',123,456.789,"abcd"}; //data就是結構體類型的變量 ? int main() { //結構體變量訪問內部成員的語法: . 點運算符 printf("%c\n",data.a); printf("%d\n",data.b); printf("%f\n",data.c); printf("%s\n",data.str); return 0; }
2.4 結構體賦值
//結構體變量訪問內部成員的語法: . 點運算符 #include "stdio.h" #include "string.h" #include <stdlib.h> ? //定義結構體數據類型 struct MyStruct { char a; int b; float c; char str[100]; }; ? int main() { struct MyStruct data;//data就是結構體類型的變量 //成員單獨賦值 data.a='A'; data.b=123; data.c=456.789; strcpy(data.str,"abcd"); //數組賦值 ? //結構體變量訪問內部成員的語法: . 點運算符 printf("%c\n",data.a); printf("%d\n",data.b); printf("%f\n",data.c); printf("%s\n",data.str); return 0; }
2.5 結構體數組
結構體賦值分為兩種標準: C89 、C99 ?結構體數組 #include "stdio.h" #include "string.h" #include <stdlib.h> ? //定義結構體數據類型 struct MyStruct { char a; int b; float c; char str[100]; }; ? int main() { struct MyStruct data[100];//data就是結構體數組類型變量 struct MyStruct data2[50]; ? //成員單獨賦值 data[0].a='A'; data[0].b=123; data[0].c=456.789; strcpy(data[0].str,"abcd"); //數組賦值 ? //結構體變量訪問內部成員的語法: . 點運算符 printf("%c\n",data[0].a); printf("%d\n",data[0].b); printf("%f\n",data[0].c); printf("%s\n",data[0].str); return 0; }
2.6 結構體指針賦值
#include "stdio.h" #include "string.h" #include <stdlib.h> //定義結構體數據類型 struct MyStruct { char a; int b; float c; char str[100]; }; ? int main() { //struct MyStruct buff[100]; //struct MyStruct *data=buff; //結構體指針類型變量 ? struct MyStruct *data=malloc(sizeof(struct MyStruct)); data->a='A'; data->b=123; data->c=456.789; strcpy(data->str,"abcd"); ? //結構體指針訪問內部成員的變量 通過 -> 運算符。 printf("%c\n",data->a); printf("%d\n",data->b); printf("%f\n",data->c); printf("%s\n",data->str); return 0; }
3. 學生管理系統
作業: 學生管理系統
需求: (每一個功能都是使用函數進行封裝) 1.實現從鍵盤上錄入學生信息。 (姓名、性別、學號、成績、電話號碼) 2.將結構體里的學生信息全部打印出來。 3.實現根據學生的姓名或者學號查找學生,查找到之后打印出學生的具體信息。 4.根據學生的成績對學生信息進行排序。 5.根據學號刪除學生信息。
示例:
#include "stdio.h" #include "string.h" #include <stdlib.h> //定義存放學生信息的結構體類型 struct StuDentInfo { char Name[20]; //姓名 int number; //學號 char phone[20];//電話號碼 }; //全局變量區域 unsigned int StuDentCnt=0; //記錄已經錄入的全部學生數量 //函數聲明區域 void PrintStuDentInfoList(void); void InputStuDentInfo(struct StuDentInfo*info); void FindStuDentInfo(struct StuDentInfo*info); void SortStuDentInfo(struct StuDentInfo*info); void PrintStuDentInfo(struct StuDentInfo*info); int main() { struct StuDentInfo data[100]; //可以100位學生的信息 int number; while(1) { PrintStuDentInfoList(); //打印功能列表 scanf("%d",&number); printf("\n"); switch(number) { case 1: InputStuDentInfo(data); break; case 2: FindStuDentInfo(data); break; case 3: SortStuDentInfo(data); break; case 4: PrintStuDentInfo(data); break; case 5: break; default: printf("選擇錯誤!\n\n"); break; } } return 0; } /* 函數功能: 打印學生管理系統的功能列表 */ void PrintStuDentInfoList(void) { printf("\n--------------學生管理系統功能列表----------------\n"); printf("1. 錄入學生信息\n"); printf("2. 根據學號查找學生信息\n"); printf("3. 根據學號排序\n"); printf("4. 打印所有學生信息\n"); printf("5. 刪除指定的學生信息\n"); printf("請選擇功能序號:"); } /* 函數功能: 錄入學生信息 */ void InputStuDentInfo(struct StuDentInfo*info) { printf("輸入學生姓名:"); scanf("%s",info[StuDentCnt].Name); printf("輸入學號:"); scanf("%d",&info[StuDentCnt].number); printf("輸入電話號碼:"); scanf("%s",info[StuDentCnt].phone); StuDentCnt++; //數量自增 } /* 函數功能: 查找學生信息 */ void FindStuDentInfo(struct StuDentInfo*info) { int num,i; printf("輸入查找的學號:"); scanf("%d",&num); for(i=0; i<StuDentCnt; i++) { if(info[i].number==num) { printf("信息查找成功,該學生的信息如下:\n"); printf("姓名:%s\n",info[i].Name); printf("學號:%d\n",info[i].number); printf("電話號碼:%s\n",info[i].phone); printf("\n"); break; } } if(i==StuDentCnt) { printf("----------%d學號不存在!---------\n",num); } } /* 函數功能: 根據學號排序 */ void SortStuDentInfo(struct StuDentInfo*info) { int i,j; struct StuDentInfo tmp; //保存臨時信息 for(i=0; i<StuDentCnt-1; i++) { for(j=0;j<StuDentCnt-i-1;j++) { if(info[j].number>info[j+1].number) { tmp=info[j]; info[j]=info[j+1]; info[j+1]=tmp; } } } } /* 函數功能: 打印所有學生信息 */ void PrintStuDentInfo(struct StuDentInfo*info) { int i=0; printf("-----------所有學生的信息列表------------\n"); for(i=0;i<StuDentCnt;i++) { printf("姓名:%s\n",info[i].Name); printf("學號:%d\n",info[i].number); printf("電話號碼:%s\n",info[i].phone); printf("\n"); } }
附:結構體變量的存儲原理
1)結構體數據成員對齊的意義
內存是以字節為單位編號的,某些硬件平臺對特定類型的數據的內存要求從特定的地址開始,如果數據的存放不符合其平臺的要求,就會影響到訪問效率。所以在內存中各類型的數據按照一定的規則在內存中存放,就是對齊問題。而結構體所占用的內存空間就是每個成員對齊后存放時所占用的字節數之和。
計算機系統對基本數據類型的數據在內存中存放的限制是:這些數據的起始地址的值要求是某個數K的倍數,這就是內存對齊,而這個數 K 就是該數據類型的對齊模數(alignment modulus)。這樣做的目的是為了簡化處理器與內存之間傳輸系統的設計,并且能提升讀取數據的速度。
結構體對齊不僅包括其各成員的內存對齊(即相對結構體的起始位置),還包括結構體的總長度。
2)結構體大小的計算方法和步驟
i. 將結構體內所有數據成員的長度值相加,記為 sum_a ;
ii. 將各數據成員為了內存對齊,按各自對齊模數而填充的字節數累加到sum_a上,記為sum_b。
對齊模數是 #pragma pack 指定的數值與該數據成員自身長度相比較得到的數值較小者。該數據相對起始位置應該是對齊模數的整數倍。
iii. 將和 sum_b 向結構體模數對齊。
該模數則是 #pragma pack 指定的數值與結構體內最大的基本數據類型成員長度相比較得到的數值較小者。結構體的長度應該是該模數的整數倍。
數據類型自身對齊:
所謂“對齊在N上”,是指“存放的起始位置是%N = 0”.
總結
原文鏈接:https://juejin.cn/post/7080696319807291423
相關推薦
- 2022-05-24 C/C++中的static關鍵字詳解_C 語言
- 2022-04-10 Python?十個字典用法使用技巧歸納_python
- 2023-06-19 圖文詳解Go中的channel_Golang
- 2022-06-29 C#集合之自定義集合類_C#教程
- 2022-05-06 excelize-golang中excel表格內容讀取
- 2022-11-02 解決SecureCRT通過SSH連接Ubuntu時vi命令有多余的m的問題_相關技巧
- 2022-12-29 Kotlin數據存儲方式全面總結講解_Android
- 2022-08-17 C語言超全面講解字符串函數_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支