memset函數及其用法,C語言memset函數詳解

2020-07-16 10:04:23
在前面不止一次說過,定義變數時一定要進行初始化,尤其是陣列和結構體這種佔用記憶體大的資料結構。在使用陣列的時候經常因為沒有初始化而產生“燙燙燙燙燙燙”這樣的野值,俗稱“亂碼”。

每種型別的變數都有各自的初始化方法,memset() 函數可以說是初始化記憶體的“萬能函數”,通常為新申請的記憶體進行初始化工作。它是直接操作記憶體空間,mem即“記憶體”(memory)的意思。該函數的原型為:

# include <string.h>
void *memset(void *s, int c, unsigned long n);

函數的功能是:將指標變數 s 所指向的前 n 位元組的記憶體單元用一個“整數” c 替換,注意 c 是 int 型。s 是 void* 型的指標變數,所以它可以為任何型別的資料進行初始化。

memset() 的作用是在一段記憶體塊中填充某個給定的值。因為它只能填充一個值,所以該函數的初始化為原始初始化,無法將變數初始化為程式中需要的資料。用memset初始化完後,後面程式中再向該記憶體空間中存放需要的資料。

memset 一般使用“0”初始化記憶體單元,而且通常是給陣列或結構體進行初始化。一般的變數如 char、int、float、double 等型別的變數直接初始化即可,沒有必要用 memset。如果用 memset 的話反而顯得麻煩。

當然,陣列也可以直接進行初始化,但 memset 是對較大的陣列或結構體進行清零初始化的最快方法,因為它是直接對記憶體進行操作的。

這時有人會問:“字串陣列不是最好用''進行初始化嗎?那麼可以用 memset 給字串陣列進行初始化嗎?也就是說引數 c 可以賦值為''嗎?”

可以的。雖然引數 c 要求是一個整數,但是整型和字元型是互通的。但是賦值為 '' 和 0 是等價的,因為字元 '' 在記憶體中就是 0。所以在 memset 中初始化為 0 也具有結束標誌符 '' 的作用,所以通常我們就寫“0”。

memset 函數的第三個引數 n 的值一般用 sizeof()  獲取,這樣比較專業。注意,如果是對指標變數所指向的記憶體單元進行清零初始化,那麼一定要先對這個指標變數進行初始化,即一定要先讓它指向某個有效的地址。而且用memset給指標變數如p所指向的記憶體單元進行初始化時,n 千萬別寫成 sizeof(p),這是新手經常會犯的錯誤。因為 p 是指標變數,不管 p 指向什麼型別的變數,sizeof(p) 的值都是 4。

下面寫一個程式:
# include <stdio.h>
# include <string.h>
int main(void)
{
    int i;  //迴圈變數
    char str[10];
    char *p = str;
    memset(str, 0, sizeof(str));  //只能寫sizeof(str), 不能寫sizeof(p)
    for (i=0; i<10; ++i)
    {
        printf("%dx20", str[i]);
    }
    printf("n");
    return 0;
}
根據memset函數的不同,輸出結果也不同,分為以下幾種情況:
memset(p, 0, sizeof(p));  //地址的大小都是4位元組
0 0 0 0 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(*p));  //*p表示的是一個字元變數, 只有一位元組
0 -52 -52 -52 -52 -52 -52 -52 -52 -52

memset(p, 0, sizeof(str));
0 0 0 0 0 0 0 0 0 0

memset(str, 0, sizeof(str));
0 0 0 0 0 0 0 0 0 0

memset(p, 0, 10);  //直接寫10也行, 但不專業
0 0 0 0 0 0 0 0 0 0