透徹分析C/C++中memset函數

在C語言中,常常須要對內存進行操做,裏面涉及不少函數,可是memset函數的使用有一點須要你們格外注意,這也是我在作項目時遇到過的一個問題,調試了好久才找出來錯誤。編程

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

    函數功能是:將s所指向的某一塊內存中的前n個字節的內容所有設置爲ch指定的ASCII值, 第一個值爲指定的內存地址,塊的大小由第三個參數指定,這個函數一般爲新申請的內存作初始化工做, 其返回值爲指向s的指針,它是對較大的結構體或數組進行清零操做的一種最快方法。函數

    頭文件是:<memory.h>或<string.h>spa

    這些解釋在百度裏面隨處可見,而這裏須要強調的是一些須要引發你們重視的關鍵點。指針

    1. 基本應用場合調試

    memset函數一般用來對一塊已經分配地址的內存進行初始化,而且一般初始化爲0或者字符'\0'(其實是同樣的)。下面是一些常見例子。

code

/*===注意:這些例子若是同時運行須要在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. 須要注意的幾點blog

(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,而是一個很大的數,結果出乎意料,因此必定要記住這一點,很是重要!!!

相關文章
相關標籤/搜索