C 程序停止使用 scanf_s

C program stops working with scanf_s

我在编程方面还很陌生,我在处理一段代码时遇到了问题。我正在尝试输入一个单词,但是当我 运行 程序并输入单词时它停止工作。

这是代码:

    int main(void){
    char a[]= ""; 

    printf("Enter word:\n");
    scanf_s("%s", a);

    return 0;
}

我尝试将 a[] 的大小设置为 20,并使用 %19s 作为另一个问题的建议,但这也没有用。

编辑 1. 将 char a[]= ""; 更改为 char a[20]= {0}; 但没有成功。

编辑 2. 添加了 sizeof(a) 并且代码有效。此外,我删除了 {0},但我不知道这是否有影响。

最终代码:

int main(void){

    char a[20]; 

    printf("Enter word:\n");
    scanf_s("%19s", a, sizeof(a));

    return 0;

}

正在使用

char a[]="";

创建一个足以容纳单个字节的数组。您必须分配足够的 space,例如像这样:

char a[20] = {0}; // Can hold a string length 19 + [=11=] termination

使用您的方法,您会遇到溢出,因为 scanf_s 写入的内存比您分配的多,从而导致分段错误。

诊断

代码中(至少)有两个问题:

  1. 您没有提供任何有用的 space 来存储字符串。 (原始问题定义:char a[] = "";,请注意,它是一个长度为 1 的数组,尽管它只能容纳长度为 0 的字符串。)

  2. 您没有告诉 scanf_s() 字符串有多大。在指向字符串的指针后需要一个长度参数。

Microsoft 对 scanf_s() 的定义指定:

Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if you are reading a string, the buffer size for that string is passed as follows:

char s[10];
scanf_s("%9s", s, _countof(s)); // buffer size is 10, width specification is 9 

The buffer size includes the terminating null. You can use a width specification field to ensure that the token that's read in will fit into the buffer. If no width specification field is used, and the token read in is too big to fit in the buffer, nothing is written to that buffer.

Note

The size parameter is of type unsigned, not size_t.

_countof() 运算符是 Microsoft 的扩展。它大约等同于 sizeof(s) / sizeof(s[0]),在这种情况下与 sizeof(s) 相同,因为根据定义 sizeof(char) == 1

请注意,大小参数是 unsigned,而不是您期望的 size_t。这是 TR 24731-1 函数的 Microsoft 实现与 ISO/IEC 9899:2011 的附件 K 之间的区别之一。标准中指定的大小在技术上是 rsize_t,但定义为 size_t,范围有限(因此 r):

The type is rsize_t which is the type size_t.

但脚注(未显示)指的是 RSIZE_MAX 的定义。

另见 Do you use the TR 24731 'safe' functions?

修正问题中的代码

引用自 Microsoft 的示例主要说明了如何修复您的代码。您需要:

int main(void)
{
    char a[4096];
    
    printf("Enter word:\n");
    if (scanf_s("%s", a, (unsigned)sizeof(a)) != 1)  // Note cast!
        fprintf(stderr, "scanf_s() failed\n");
    else
        printf("scanf_s() read: <<%s>>\n", a);
    
    return 0;
}

请注意,我检查了 scanf_s() 的结果,而不是假设它有效,并报告了标准错误的错误。