malloc

Prerequisites:

語法

1
void* malloc(size_t size)

傳回值型態

由於malloc傳回的類型是void*指標位址,void*可以強轉成任何型態。

傳回值是void*要強制轉型

傳回記憶體空間的起始位址。

例:建立5個int空間,int空間占4byte,也就是建立5 * 4byte = 20byte。

下圖中,p變數指向第1個int空間的起始位址,總共建立5個int空間。
img

1
2
  int len = 5;
  int* p = (int * )malloc(len * sizeof(int));

其它範例:

1
2
char* p1 = (char* )malloc(10);  // 10byte
int* p2 = (int* )malloc(1 * 1024 * 1024);  // 1byte * 1024 = 1kb ->1kb * 1024=1mb

參數size_t

size_t是無正負號,unsigned int整數。

參數size_t size代表設定空間大小,單位是byte。

也可以這樣定義

1
2
3
// int 4byte * 10 = 40 byte
// 申請40byte的記憶體空間
int* num = (int* )malloc(sizeof(int) * 10);

char是1byte,就不用寫sizeof(char)。

1
char* name = (char* )malloc(100);

初始化memset

-memset 把指標所指向的記憶體內容,初始化。
以下是把p指標所指向的記憶體空間,全變成0。

c++的0,就是nullptr、NULL。

各種型態的預設值都是0,char的\0,也是0,對映ASCII CODE碼\0就是整數0。

型態 預設值
int 0
char \0
float 0.0
double 0.0
指標類型 NULL
1
2
3
size_t size = 1 * 1024 * 1024;
void* p = malloc(size);
memset(p, 0, size);  // 初始化都為0

記憶體回收

void free(void* p);
  • 參數 p 原有malloc或calloc分配的指標「起始位址」

注意!是起始位址。

所謂的記憶體回收,是指這個空間已經沒有人使用了,還給系統,並沒有清空
只是告訴系統,這塊空間已經沒人用。
下一次系統可以分配變數使用這個記憶體空間。

1
free(p2);

下面的程式,func()函式執行完後,區域變數n已經被系統回收。
main()函式,試圖把func()函式中的n變數取出來,但印出的值已經不是100,因為原本n的記憶體空間已經被系統拿去放”test test”的內容,所謂的回收,就是告訴系統這塊記憶體空間不使用,可以拿來放其它的值。

1
2
3
4
5
6
7
8
9
10
11
12
int* func() {
  int n = 100;
  return &n;
}
int main() {
  int* p = func();
  int n;
  printf("test test\n");
  n = * p;
  printf("%d\n",n);
  return 0;
}
test test
-610123577

指標p設為nullptr

記憶體回收完畢,要把p2指標指向nullptr。
不能讓p2指標指向「已回收」的記憶體空間。
p2也可以指向0。
p2也可以指向NULL。
都是相同的意思。

1
2
3
4
free(p2);  
p2 = nullptr;
// p2 = 0;  
// p2 = NULL    

建立陣列

以下程式碼建立大小為5的整數(4 byte)陣列。
sizeof(int)為4byte。
大小 = 5 * 4byte = 20 byte

空間建立完後,會有一個記憶體空間,裡面有5個空間,每個空間都是4byte。
p指標指向記憶體空間的起始位址。
img

指標移動

因為是int*的指標,所以每一次移動都是移動4byte。

p是記憶體位址,p = 0x1000,+ 1 代表記憶體位址 + 4 byte。
p + 0 = 0x1000 + 0byte = 0x1000
p + 1 = 0x1000 + 4byte = 0x1004
p + 2 = 0x1000 + 8byte = 0x1008
p + 3 = 0x1000 + 12byte = 0x100C
p + 4 = 0x1000 + 16byte = 0x1010
img

p++ 就是 p = p + 1,+ 1 代表記憶體位址 + 4 byte。

但這邊有用等於,代表每移動1次,p變數也會修改。

因為p會修改,所以下面程式使用p2記錄p指標一開始的起始位址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main() {
  int len = 5;
  // p 指向起始位址
  int* p = (int * )malloc(len * sizeof(int));
  // 記錄p指標一開始的起始位址
  int* p2 = p;
  for (int i = 0; i < len; i++) {
    // 記憶體位址的值,指派為i變數
    * p = i;
    // p = p + 1,每移動一次,p的位址也會更改
    p++;
  }
  for (int i = 0; i < len; i++) {
    // 使用p2印出值
    cout << * (p2 + i) << ", ";
  }
  cout << endl;
  // 記憶體位址回收
  // p2記錄p指標一開始的起始位址,p指標已經移位
  free(p2);
  // p2指標設為null
  p2 = nullptr;  
  return 0;
}
0, 1, 2, 3, 4, 

results matching ""

    No results matching ""