C語言 memset 函式全攻略:語法、實用範例與注意事項

1. memset是什麼?概要與用途

memset是C語言中常用的記憶體操作函式之一,用於將一段記憶體區域以指定值進行初始化。這個函式會以位元組為單位,把指定的數值寫入到選定的記憶體區塊內,非常適合用來快速清除記憶體內容。主要應用在陣列初始化或加強安全性(例如清除敏感資料)。

  • 例子:初始化陣列、清除敏感資料等

正確使用這個函式,可以讓程式的記憶體管理更有效率,同時也能提升資訊安全。

2. memset函式的基本用法

2.1 memset函式的語法

memset的基本語法如下:

#include <string.h>
void *memset(void *buf, int ch, size_t n);
  • 第一個參數(buf:要初始化的記憶體區塊起始位址。
  • 第二個參數(ch:要寫入記憶體的數值(以位元組方式存放)。
  • 第三個參數(n:要設定的位元組數量。

2.2 memset的使用範例

以下範例展示如何用特定值初始化陣列的一部分。

#include <stdio.h>
#include <string.h>

int main() {
    char buf[10] = "ABCDEFGHIJ";
    // 從第3個位元組(索引2)開始,填入3個'1'
    memset(buf + 2, '1', 3);
    printf("buf字串→%s
", buf); // 輸出: "AB111FGHIJ"
    return 0;
}

在此範例中,使用memsetbuf陣列從第2個位元組開始的3個位元組全部設為'1'。輸出結果為"AB111FGHIJ",可以看到指定區域已被’1’取代。

侍エンジニア塾

3. memset的實用範例

3.1 陣列初始化

memset常用來初始化整個陣列,使所有元素設定為指定的值。以下範例將陣列全部設為0:

#include <stdio.h>
#include <string.h>

int main() {
    int arr[10];
    memset(arr, 0, sizeof(arr));
    return 0;
}

這裡是將arr陣列所有元素全部歸零。

3.2 記憶體清除與安全強化

memset也可以用來清除如密碼、加密金鑰等敏感資料。以下是清除密碼的例子:

#include <string.h>

void clearPassword(char *password) {
    // 密碼使用完畢後,將其歸零
    memset(password, 0, strlen(password)); // 清空密碼
}

確保敏感資料不會殘留在記憶體中,有助於提升系統安全性。

3.3 搭配動態記憶體配置

malloc分配的動態記憶體,也可用memset來初始化。例如:

#include <stdlib.h>
#include <string.h>

int main() {
    char *buffer = (char *)malloc(50);
    if (buffer == NULL) {
        return 1; // 記憶體分配失敗
    }
    // 初始化記憶體為0
    memset(buffer, 0, 50);
    free(buffer); // 釋放記憶體
    return 0;
}

4. memset使用注意事項

4.1 防止緩衝區溢位(Buffer Overflow)

使用memset時,必須確保設定的大小不要超出記憶體區塊範圍。若指定過多位元組,可能覆蓋到其他資料。建議使用sizeof取得正確大小:

char buffer[10];
memset(buffer, 0, sizeof(buffer)); // 正確指定大小

4.2 資料型態的影響

memset以位元組為單位設定記憶體,因此若非以0來初始化整數或浮點數型態,可能會產生非預期結果。特別是結構體含有多種型態時,更要特別小心。

4.3 預防編譯器最佳化

若用memset來清除敏感資料,必須注意某些編譯器可能會將這段程式碼優化掉(即實際執行時沒真正清除記憶體)。這種情況下,建議用volatile關鍵字或memset_s等安全版本函式:

volatile char *secure_clear = memset(password, 0, strlen(password));

5. memset與其他記憶體操作函式比較

5.1 與memcpy的差異

memsetmemcpy都屬於記憶體操作函式,但用途不同:

  • memset:用來將整個記憶體區塊設定為同一個值(單一位元組)。
  • memcpy:用來從另一段記憶體區塊複製內容(任何數據)。不適合用於初始化。

5.2 與for迴圈的比較

memsetfor迴圈都能用來初始化陣列,各有優缺點:

  • memset的優點:語法簡潔、可讀性高、通常比for迴圈更快(因為經過最佳化)。
  • for迴圈的優點:可對每個元素設定不同的值,初始化更有彈性。
int array[5];
for (int i = 0; i < 5; i++) {
    array[i] = i; // 每個元素可設定不同值
}

6. 總結

memset是高效能的記憶體初始化與清除工具,但必須正確指定大小並注意資料型態的影響。只要小心使用,不僅能提升程式效能,也能強化安全性。

7. 參考資料

侍エンジニア塾