首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言核心技能:從零手寫 memset 並揭秘「置 1 變大數」陷阱

     編輯:關於C語言

C語言核心技能:從零手寫 memset 並揭秘「置 1 變大數」陷阱

memset 是 C 語言初學者最早接觸的庫函數之一,常用於「數組清零」。但若嘗試用它將 int 數組逐元素置為 1,結果往往大跌眼鏡。本文帶你手寫 memset,並從內存佈局角度徹底講清這個經典陷阱。

一、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;
}

二、為什麼「置 1」會得到 16843009?

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% 的初學者坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved