首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言 malloc 分配內存後 scanf 直接用指針讀取的正確性分析

     編輯:程式設計綜合問答

C 語言動態內存分配後,scanf 直接使用指針讀取字符串是否合法?本文分析指針解引用與 scanf 格式匹配的關係,澄清常見誤解。

代碼現場

int main() {
    char *a;
    a = (char *)malloc(40);   // 分配 40 字節
    scanf("%s", *a);          // 這裡 *a 是 char 類型,而非 char*
    return 0;
}

關鍵問題:*a 類型錯誤

表達式類型scanf("%s", ...) 期望類型結果
achar *char * (緩衝區地址)✅ 正確
*achar (首字符值)char *❌ 類型不匹配,未定義行為

正確寫法

scanf("%s", a);        // 直接傳指針 a (地址)
// 或
scanf("%s", &a[0]);    // 等價,首元素地址

為什麼原代碼「能跑通」?

  • 未定義行為 (UB):C 標準不保證結果
  • 典型表現:*a 取首字符值 (如 0),作為地址傳給 scanf → 寫入地址 0x0 → 段錯誤
  • 若首字符恰好為可寫地址 (極低概率) → 寫入隨機內存 → 靜默數據損壞
  • 某些編譯器/運行庫可能容錯,但不可依賴

完整安全模式

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *buffer = malloc(40);
    if (!buffer) {
        perror("malloc failed");
        return 1;
    }
    
    // 限制輸入長度防止溢出 (留 1 字節給 '\0')
    if (scanf("%39s", buffer) != 1) {  // %39s 最多讀 39 個非空白字符
        fprintf(stderr, "Input error\n");
    } else {
        printf("Read: %s\n", buffer);
    }
    
    free(buffer);
    return 0;
}

關鍵點總結

  1. malloc 返回 void*,轉型為 char* 即緩衝區起始地址
  2. scanf("%s", ptr) 要求 ptr 為 char*,指向可寫內存
  3. *ptr 解引用得到 char,不是地址,不可傳給 %s
  4. 必檢查 malloc 返回值,必限制輸入寬度 (如 %39s),必 free

總結

代碼 scanf("%s", *a) 不合法:*a 類型為 char,而 %s 需 char*。正確用法 scanf("%39s", a)。動態內存讀取字符串需「檢查分配、限制寬度、釋放內存」三部曲。

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