1. 程式人生 > >memset函式詳解

memset函式詳解

在C語言中,經常需要對記憶體進行操作,裡面涉及很多函式,但是memset函式的使用有一點需要大家格外注意,這也是我在做專案時遇到過的一個問題,除錯了很久才找出來錯誤。

    函式原型是:void *memset(void *s, int ch, size_t n);

    函式功能是:將s所指向的某一塊記憶體中的前n個位元組的內容全部設定為ch指定的ASCII值, 第一個值為指定的記憶體地址,塊的大小由第三個引數指定,這個函式通常為新申請的記憶體做初始化工作, 其返回值為指向s的指標,它是對較大的結構體或陣列進行清零操作的一種最快方法。

    標頭檔案是:<memory.h>或<string.h>

    這些解釋在百度裡面隨處可見,而這裡需要強調的是一些需要引起大家重視的關鍵點。

    1. 基本應用場合

    memset函式通常用來對一塊已經分配地址的記憶體進行初始化,並且通常初始化為0或者字元'\0'(實際上是一樣的)。下面是一些常見例子。

/*===注意:這些例子如果同時執行需要在C++編譯環境下===*/

int i = 0;

// 例1:對字元陣列進行初始化

char buf[10];

memset(buf, '\0', sizeof(char) * 10); // 0或者'\0'是等價的

for (i = 0; i < 10; ++i)

{

printf("%c", buf[i]);

}

printf("\n");

// 例2:對字元指標所指區域初始化,必須已經分配記憶體

char* pBuf = (char *)malloc(sizeof(char) * 10);

if (pBuf != NULL)

{

memset(pBuf, 0, sizeof(char) * 10); // 0或者'\0'是等價的

for (i = 0; i < 10; ++i)

{

printf("%c", pBuf[i]);

}

printf("\n");

free(pBuf);

pBuf = NULL;

}

// 例3:對整型陣列進行初始化

int iBuf[10];

memset(iBuf, 0, sizeof(int) * 10);

for (i = 0; i < 10; ++i)

{

printf("%d ", iBuf[i]);

}

printf("\n");

    上面的這些例子已經比較清楚地展示了memset函式的使用,當然,很常見的還有對結構體進行這樣的初始化操作,唯一的區別就是sizeof()的物件變成結構體即可,這裡大家可以自己嘗試。

    2. 需要注意的幾點

(1)memset中的第三個引數一定要使用sizeof操作符,因為每個系統下對型別長度的定義可能不一樣。

(2)memset中的第一個引數一定要是一個已知的、已經被分配記憶體的地址,否則會出錯。

(3)大家可能比較疑惑,memset的第一個引數已經有了被初始化空間的首地址,為什麼還要返回一個void*的指標去指向這個地址呢?這種結構在很多函式庫裡面比較常見,比如字串操作函式等,都有類似的現象,這裡之所以還要返回這個指標是為了實現鏈式程式設計,所謂鏈式程式設計,舉個例子大家就明白了。

// 例4:鏈式程式設計

int i = 0;

char cBuf [10];

char cBuf1[10];

// 這裡是關鍵!!!

memcpy(cBuf1, memset(cBuf, 'a', sizeof(char) * 10), sizeof(char) * 10);

for (i = 0; i < 10; ++i)

{

printf("%c", cBuf[i]);

}

printf("\n");

for (i = 0; i < 10; ++i)

{

printf("%c", cBuf1[i]);

}

printf("\n");

    從上面這個例子中就可以看出,在memcpy這個函式中,直接使用了memset的返回值,用其來拷貝cBuf1這個字元陣列,這樣就可以直接連起來寫,看起來十分方便。但是這個例子的應用形式卻很少,只是為了說明這個問題才這樣寫的,具體的鏈式程式設計應用場合大家可以再仔細研究下,但是鏈式程式設計也使得程式碼變得有些不直觀,所以要有所取捨。

(4)最後一點,也是最重要的一點。一定要注意,memset是按照位元組對待初始化空間進行初始化的,也就是說,函式裡面的第二個引數的那個初值(一般為0)是按照一個一個位元組往第一個引數所指區域賦值的,所以,對於單位元組資料型別(char)可以初始化為任意支援的值,都沒有問題,但是對於非多位元組資料型別只能初始化為0,而不能初始化成別的初值,因為對所有位元組按任意順序賦值0的結果都是0,而如果初始化為其他的值,就會一個位元組一個位元組的進行賦值,從而出現奇怪的結果。比如說,上面的例3之所以沒有出錯就是因為初始化為0,但是如果初始化為1,那麼因為int一般是4個位元組,那麼相當於將一個int元素初始化成了0000 0001 0000 0001 0000 0001 0000 0001,這樣對於一個int元素肯定不是1,而是一個很大的數,結果出乎意料,所以一定要記住這一點,非常重要!!