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

VS2013 scanf_s 緩衝區大小參數缺失導致結構體輸入跳過:C11 安全函數正確用法詳解

     編輯:程式設計綜合問答

現象描述

VS2013 中結構體輸入:輸入名字後程序直接結束,後續 `scanf_s` 全被跳過。Dev-C++ (GCC) 正常。

根本原因

`scanf_s` 是 C11 可選安全函數,**`%s`/`%c` 格式必須提供緩衝區大小參數**;VS 強制要求,GCC 默認不強制。

錯誤 vs 正確代碼


// ❌ 錯誤:缺少大小參數
scanf_s("%s", &me.name);
scanf_s("%s", &me.sex);

// ✅ 正確:提供緩衝區大小(字符數,含結束符)
scanf_s("%s", &me.name, (unsigned)_countof(me.name));  // 10
scanf_s("%s", &me.sex, (unsigned)_countof(me.sex));    // 5

// 或手動指定
scanf_s("%s", me.name, 10);
scanf_s("%s", me.sex, 5);

scanf_s 參數規則速查

格式符額外參數含義
%s緩衝區大小 (rsize_t)最大讀入字符數(含\0)
%c緩衝區大小通常為 1
%[...]緩衝區大小字符集匹配
%d/%f/%p...無非字符串類型無需大小

結構體輸入完整修正版


#include 
#include 

struct People {
    char name[10];
    char sex[5];
    int age;
    int Class;
};

int main() {
    struct People me;
    
    printf("Please Input Your Name\n");
    // 注意:數組名即地址,無需 &,_countof 需  或手動計算
    scanf_s("%9s", me.name, (unsigned)sizeof(me.name));  // %9s 防溢出,大小含\0
    
    printf("Please Input Your Sex\n");
    scanf_s("%4s", me.sex, (unsigned)sizeof(me.sex));
    
    printf("Please Input Your Age\n");
    scanf_s("%d", &me.age);
    
    printf("Please Input Your Class\n");
    scanf_s("%d", &me.Class);
    
    printf("Name: %s\nSex: %s\nAge: %d\nClass: %d\n", me.name, me.sex, me.age, me.Class);
    system("pause");
    return 0;
}

跨平台兼容方案


// 宏適配:MSVC 用 scanf_s,GCC/Clang 用 scanf
#if defined(_MSC_VER)
#define MY_SCANF_S(fmt, ...) scanf_s(fmt, __VA_ARGS__)
#else
#define MY_SCANF_S(fmt, ...) scanf(fmt, __VA_ARGS__)
#endif

// 使用
MY_SCANF_S("%s", me.name, sizeof(me.name));  // GCC 忽略額外參數

現代 C++ 替代方案(推薦)


#include 
#include 
#include 

struct People {
    std::string name;
    std::string sex;
    int age;
    int Class;
};

int main() {
    People me;
    std::cout << "Name: "; std::getline(std::cin, me.name);
    std::cout << "Sex: "; std::getline(std::cin, me.sex);
    std::cout << "Age: "; std::cin >> me.age; std::cin.ignore(std::numeric_limits::max(), '\n');
    std::cout << "Class: "; std::cin >> me.Class;
    // ...
}

總結

VS2013 強制執行 C11 `scanf_s` 緩衝區大小檢查。**`%s/%c` 必須加大小參數**,否則行為未定義(跳過輸入、崩潰、靜默截斷)。跨平台代碼請用宏適配,或直接用 C++ iostream 徹底避開 C 安全函數陷阱。

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