memset 是 C 語言初學者最早接觸的庫函數之一,常用於「數組清零」。但若嘗試用它將 int 數組逐元素置為 1,結果往往大跌眼鏡。本文帶你手寫 memset,並從內存佈局角度徹底講清這個經典陷阱。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *my_memset(void *p1, int val, size_t count) {
char *dest = (char *)p1;
char *ret = dest; // 保存起始地址用於返回
while (count--) {
*dest = (char)val; // 只取 val 低 8 位
dest++;
}
return ret;
}
int main() {
int arr[] = { 1, 3, 5, 6, 8, 9 };
int *ret = (int *)my_memset(arr, 1, 16); // 16 字節 = 4 個 int
for (int i = 0; i < 6; i++) {
printf("%d ", ret[i]);
}
system("pause");
return 0;
}
memset 按「字節」填充。val = 1 時,每個字節被寫入 0x01。int 佔 4 字節(小端模式),內存呈現為:
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
對應的十進制 int 值為:
0x01010101 = 16843009
這就是輸出全是 16843009 的根本原因。
memset(arr, 0, sizeof(arr)) —— 全 0 位模式對所有整數/浮點類型均表示 0,安全可靠。std::fill(C++),切勿用 memset。memset 將指針置為 NULL、浮點置為 0.0,通常符合預期,但嚴格說依賴實現定義行為,建議逐字段初始化。memset 本質是「字節級填充工具」,只適合清零(全 0 位模式)及字符數組填充。理解其按字節操作的特性,能避開 90% 的初學者坑。