c语言 12大于12么,【C语言】第十二章
8種機械鍵盤軸體對比
本人程序員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎么選?
為什么會出現動態內存分配
這個問題要結合數組來進行討論。在C99之前的標準中,C語言中數組的定義要求必須給定常量的大小才能定義數組,也就是說數組變量的內存空間在編譯時就已成定局,無法更改。那我們如果想要申請一塊內存空間,空間大小在運行時才進行確定該怎么做呢?這就要用到動態的內存分配了,這里的空間大小的確定是在運行時才進行確定的。
動態內存分配函數
malloc和free
在內存的動態分配中,首當其沖最為重要的兩個函數就是malloc和free函數,它們挑起了動態內存分配的大梁。
malloc函數負責向計算機申請一塊連續的內存空間,并且返回指向該塊內存的指針。
void* malloc(size_t size);
但是值得注意的是malloc所返回的指針的類型是void*型,所以在實際使用中我們往往要進行牽制類型轉換將其轉換為我們想要的指針類型。關于這個函數還有以下幾點說明。
1、如果開辟空間成功則返回一個指向該空間的指針。
2、如果開辟空間失敗則返回NULL。
3、如果參數為0則是未定義行為。
4、返回類型為void*所以編譯器并不知道所開辟的空間的類型,由使用者決定。
既然開辟了空間,并且這個空間編譯器不會幫我們自動將其釋放那么就必然要求我們在使用完畢后將其釋放,不浪費內存空間不造成泄露,因此就出現了free函數。
void free (void* ptr);
1、如果參數ptr的不是動態開辟的則行為是未定義的。
2、如果參數ptr == NULL則函數什么都不做。
malloc和free函數都在stdlib.h頭文件中。
以下舉一個動態分配內存并且釋放的例子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include
#include
int main()
{
int n = 0;
printf("請輸入要分配的數組的內存空間的大小:");
scanf("%d", &n);
int* array = (int*)malloc(sizeof(int) * n);
printf("分配成功!n");
printf("請給數組賦值:");
for(int i = 0; i < n; i++)
{
scanf("%d", &array[i]);
}
for(int i = 0; i < n; i++)
{
printf("%dt", array[i]);
}
printf("n");
free(array);
array = NULL;
printf("數組已經釋放!n");
}
請輸入要分配的數組的內存空間的大小:8
分配成功!
請給數組賦值:1
2
3
4
5
6
7
8
12345678
數組已經釋放!
在以上這個例子中我們動態地在程序運行時對一個數組進行了空間的分配,并且讓用戶對數組進行了賦值,之后打印,數組使用完畢后我們又用free函數將其空間釋放。這是一個很簡單但是很實用的動態內存分配的例子。在這個例子中要尤為記住的一點是我們在進行動態的內存分配后一定不能忘記在使用完畢后將內存空間釋放,并且將指針賦值為NULL,這一點是十分關鍵的,否則將造成內存泄漏和野指針,對程序造成很大的影響。
往往內存泄漏不是我們忘記free而是不經意間造成的,以下就是一個典型的內存泄漏的例子。1
2
3
4
5
6
7
8
9#include
#include
int main()
{
int* p = (int*)malloc(sizeof(int));
p = (int*)malloc(sizeof(int));
free(p);
p = NULL;
}
這個例子中我們明明進行了釋放卻也造成了內存泄漏,這是因為我們申請了兩次內存空間,但是用同一個指針來接收,只釋放了一次,因此造成了內存的泄漏。因此我們在實際使用中牽扯動態內存分配的時候都一定要小心又小心。
calloc
C語言還提供了一個函數進行動態內存分配。這個函數與malloc函數很相似,但是有一點不同的是這個函數會自動進行初始化。但是初始化有時候也不盡然全是好事,當我們要申請一個特別大的空間時,初始化會浪費很多很多的時間。
void* calloc(size_t num, size_t size);
calloc的功能是分配num個大小為size的內存空間,并將內存空間初始化為0。舉個例子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include
#include
int main()
{
int n = 0;
printf("請輸入數組長度:");
scanf("%d", &n);
int* array = (int*)calloc(n, sizeof(int));
for(int i = 0; i < n; i++)
{
printf("%dn", array[i]);
}
free(array);
}
請輸入數組長度:8
0
0
0
0
0
0
0
0
在以上這個例子中我們看到calloc確實可以進行動態內存分配并且進行了初始化,但是這也是又兩面性的。因此也要謹慎使用。
realloc
當我們將內存空間進行動態分配后我們如果想要擴大我們分配的內存該怎么做呢?我們可以分配一塊新的內存然后將原來內存中的數據再放到新的內存中。但是在C語言標準庫中為了方便已經給我們準備了這么一個擴容函數realloc。
void* realloc(void* ptr, size_t size);
ptr是要調整大小的內存空間,size是調整后的大小。至于計算機是怎么進行擴容的呢?這里要分兩種情況。
1、如果目標內存空間后面有足夠大小的空間則直接將后面的空間歸入目標空間中即可。
2、如果目標空間后面沒有足夠大小的空間則在內存中重新尋找一片足夠大小的空間進行開辟并且將原來的數據放入到新的空間中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include
#include
int main()
{
int n = 0;
printf("請輸入數組的長度:");
scanf("%d", &n);
int* array = (int*)malloc(sizeof(int) * n);
printf("請輸入目標擴容的大小:");
scanf("%d", &n);
array = (int*)realloc(array, n * sizeof(int));
printf("擴容成功!n");
printf("請給數組賦值:");
for(int i = 0; i < n; i++)
{
scanf("%d", &array[i]);
}
printf("打印數組:");
for(int i = 0; i < n; i++)
{
printf("%dn", array[i]);
}
}
請輸入數組的長度:5
請輸入目標擴容的大小:8
擴容成功!
請給數組賦值:1
2
3
4
5
6
7
8
打印數組:1
2
3
4
5
6
7
8
以上這個例子我們成功對已經分配的內存空間進行了擴容。
常見動態內存錯誤
1、對NULL指針的解引用操作。
2、對動態開辟空間越界訪問。
3、對非動態內存使用free釋放。
4、釋放一塊動態開辟內存的一部分。
5、對同一塊內存多次釋放。
6、動態開辟內存忘記釋放。
以上的錯誤都是十分常見的,因此我們在對內存進行操作的時候一定要萬分小心。
C/C++程序內存開辟
在這里將詳細介紹下計算機內存中的幾個區域。
1. 棧區(stack):在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些
存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有
限。 棧區主要存放運行函數而分配的局部變量、函數參數、返回數據、返回地址等。
2. 堆區(heap):一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。分配方式類似
于鏈表。
3. 數據段(靜態區)(static)存放全局變量、靜態數據。程序結束后由系統釋放。
4. 代碼段:存放函數體(類成員函數和全局函數)的二進制代碼。
通常我們定義的變量都存在棧區,動態分配內存時變量的空間都是在堆區上進行分配的,堆區有著更大更充足的空間。由此一來我們對動態內存分配就有了更深的了解。
柔性數組
柔性數組是在C99中最新的語法,其允許在結構體中最后一個成員是一個位置大小的數組,這就是柔性數組。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include
#include
typedef struct st_type
{
int i;
int a[];//柔性數組成員
}type_a;
int main()
{
type_a* p = (type_a*)malloc(sizeof(type_a) + sizeof(int) * 10);//為結構體分配內存空間
p->i = 0;
for(int i = 0 ;i < 10; i++)
{
p->a[i] = 0;
}
for(int i = 0; i < 10; i++)
{
printf("%dn", p->a[i]);
}
free(p);
}
0
0
0
0
0
0
0
0
0
0
在以上這個例子中我們使用了柔性數組,在使用柔性數組的時候我們要對結構體進行動態內存分配,并且分配的空間要大于結構體除柔性數組外的空間。
柔性數組的特點:
1、結構體中柔性數組前面必須至少一個其他成員。
2、sizeof測量結構體大小不包括柔性數組的大小。
3包含柔性數組的結構體用malloc進行內存動態分配,并且分配的內存大于結構體大小以適應 預期大小。
總結
以上是生活随笔為你收集整理的c语言 12大于12么,【C语言】第十二章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求二叉树指定结点到根的路径c语言,二叉树
- 下一篇: c语言cnn实现ocr字符,端到端的OC