在定義局部字符數組時,未初始化會包含隨機垃圾值。標準庫提供 memset 高效完成內存填充。本文深入解析其用法、常見誤區,並從零手寫實現對比源碼。
#includevoid *memset(void *s, int c, size_t n);
s:目標內存起始地址(void* 通用指針)c:填充字節值(取低 8 位,unsigned char)n:填充字節數s,支持鏈式調用#include#include #define SIZE 16 int main() { char str[SIZE]; // 未初始化,內容不定 printf("舊字符串: %s\n", str); // 輸出亂碼 memset(str, 'a', SIZE * sizeof(char)); // 填充 'a' printf("新字符串: %s\n", str); // 輸出 aaaaaaaaaaaaaaaa return 0; }
sizeof(char) 保證可移植性雖然 sizeof(char) == 1 恆成立,但寫成 SIZE * sizeof(char) 語義更清晰,擴展到其他類型(如 int arr[10]; memset(arr, 0, 10 * sizeof(int)))時不易出錯。
void* 轉為 char* 逐字節操作n 次,每次賦值 c 並移動指針void *diy_memset(void *s, char c, int n) {
if (s == NULL) return NULL; // 防御性檢查
char *p = (char *)s;
while (n > 0) {
*p = c;
p++;
n--;
}
return s;
}
void *memset(void *s, int c, size_t count) {
char *xs = (char *)s;
while (count--)
*xs++ = c;
return s;
}
| 維度 | DIY 版本 | 內核版本 |
|---|---|---|
| 空指針檢查 | 有 | 無(調用者保證) |
| 參數類型 | char c, int n | int c, size_t count |
| 循環寫法 | while(n>0) {n--;} | while(count--) 更簡潔 |
| 指針遞增 | 分兩句 | *xs++ = c 單句完成 |
| 核心邏輯 | 完全一致 | 完全一致 |
int arr[10]; memset(arr, 1, sizeof(arr)); // 錯誤!每個 int 變成 0x01010101 = 16843009
memset 按字節填充,只適用於:
struct Student { int id; char name[20]; double score; };
struct Student stu;
memset(&stu, 0, sizeof(stu)); // 所有成員歸零
char buf[100]; memset(buf, '*', 50); // 前 50 字節填 '*' buf[50] = '\0'; // 手動添加結束符
memset 是按字節填充內存的高效工具,核心場景是清零和字符填充