1. 程式人生 > 實用技巧 >C語言學習筆記_記憶體資料和字串

C語言學習筆記_記憶體資料和字串

C語言學習筆記_記憶體資料和字串

malloc和堆記憶體

// 堆記憶體需要手動申請,手動釋放,一般用於大量記憶體的使用
// 申請的函式為malloc以及相關函式,釋放函式為free
// malloc函式的返回值為void*,即返回一個指標,指向的資料型別可任意強制轉換
// 在gcc中,malloc按照塊分配,一塊 為16Byte的記憶體

// 接下里的幾個方式分配的記憶體大小均為16Byte
int* p1 = (int*)malloc(4);
int* p2 = (int*)malloc(0);

C語言的存放資料和程式碼的各個分段

程式碼段:可執行的函式存放於此,有些特殊資料會被放到程式碼段(即資料不可被修改):

// 這樣申明的s會被存放之程式碼段,使得不可被修改,因此會導致段錯誤;
char* s  = "linux";
*(s+0) = 'f';

// const定義的常量會被放到程式碼段,使得資料不可被修改
// 注意在gcc中不是如此,gcc不會放置程式碼段,因此gcc中可以繞過編譯器使得資料可以修改
const int x = 10;

資料段:顯示初始化為非零的全域性變數和靜態區域性變數放在資料段;注意,普通的區域性變數屬於函式的資料,分配在棧記憶體中;

// 堆記憶體和資料段幾乎擁有完全相同的屬性,大部分時候是可以完全替換的,但是生命週期不一樣
// 堆記憶體的生命週期從malloc開始,free結束;
// 而全域性變數是從整個程式一開始就存在,程式回收才消失;
// 堆記憶體適用於程式的階段性存在的變數,全域性變數適用於程式一直存在的變數
// 堆記憶體的使用比全域性變數廣泛

bss段:未初始化或顯示初始化為0的全域性變數放在bss段;和資料段無本質區別,幾乎可以不用明確區分;

字串和字元陣列的細節

// 定義一個數組s1,陣列佔6個位元組,右值"linux"只存在於編譯器中,初始化陣列s1後即被丟棄;
// 本定義相當於char s1[] = {'l', 'i', 'n', 'u', 'x'};
// 若在函式內,則陣列存在於棧記憶體中,陣列可被更改;
char s1[] = "linux";

// 定義字元指標p,佔4個位元組,指標存在於棧記憶體中;
// 定義了字串"linux",存在於程式碼段,內容不可被修改,程式碼段字串的首地址賦值給了p; 
char *s2 = "linux";

字串存放在不同的位置:

#include <stdio.h>
#include <stdlib.h>
char a[7];

int main(void) {
    char b[7] ;
    //  字串存在棧記憶體;
    char *p1 = b;
    
    // 字串存在資料段;
    char *p2 = a;
    char *p2 = "linux";
    
    // 字串存在堆記憶體;
    char *p3 = (char*)malloc(3*sizeof(char));
	return 0;
}