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

C語言指針參數賦值陷阱:為什麼直接賦值失效而strcpy/逐字符賦值生效

     編輯:關於C

核心誤區

函數參數傳遞的是指針的副本(按值傳遞)。函數內修改副本指向的內存內容有效,修改副本本身指向對調用者無效。

四種賦值方式實測

方式代碼結果原理
直接賦值 ❌mallo = "bag";失效修改局部指針副本指向字符串常量區,返回後銷毀
逐字符賦值 ✅*(mallo++) = 'a'+rand()%26;生效解引用寫入調用者分配的堆內存
臨時指針賦值 ✅char *t=mallo; *(t++) = ...;生效保護原指針值,邏輯更清晰
strcpy ✅strcpy(mallo, "bag");生效庫函數逐字節拷貝含\0結束符

內存模型視角解析

調用者棧幀          被調用者棧幀          堆區
┌─────────────┐     ┌─────────────┐     ┌─────────────────┐
│ mallo ──────┼────►│ mallo (副本)│────►│ 36 bytes heap   │
└─────────────┘     └─────────────┘     └─────────────────┘
      ▲                                      │
      │                                      │
      └──────── 修改*內容 可見 ──────────────┘
      ▲
      │
      └──────── 修改指針本身 不可見 ─────────┘

完整可運行示例

#include 
#include 
#include 

void memtest(char *mallo) {
    // strcpy(mallo, "bag");      // 方式4:生效
    // mallo = "bag";             // 方式1:失效!
    for (int i=0; i<36; i++)     // 方式2:生效
        mallo[i] = 'a' + rand()%26;
}

int main() {
    char *mallo = malloc(36);
    printf("Before: %s\n", mallo);  // 亂碼
    memtest(mallo);
    printf("After:  %s\n", mallo);  // 隨機字母串
    free(mallo);
    return 0;
}

避坑檢查清單

  1. 函數參數為T*時,函數內只能修改*內容,不能修改指針本身
  2. 需修改指針指向時,傳遞T**(二級指針)或返回新指針
  3. 字符串操作優先用strcpy/strncpy/snprintf
  4. 分配內存後必須檢查NULL,使用完配對free
  5. 包含<string.h>確保庫函數聲明可見
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved