诊断
代码中有(至少)两个问题:
您没有提供任何有用的空间来存储字符串。(最初的问题定义:char a[] = "";
,它——请注意——是一个长度为 1 的数组,尽管它只能保存一个长度为 0 的字符串。)
你还没有告诉scanf_s()
字符串有多大。它在指向字符串的指针之后需要一个长度参数。
Microsoft 的定义为scanf_s()
:
与scanf
and不同wscanf
,scanf_s
and要求为包含在、、、或字符串控制集wscanf_s
类型的所有输入参数指定缓冲区大小。以字符为单位的缓冲区大小作为附加参数传递,紧跟在指向缓冲区或变量的指针之后。例如,如果您正在读取一个字符串,则该字符串的缓冲区大小按如下方式传递:c
C
s
S
[]
char s[10];
scanf_s("%9s", s, _countof(s)); // buffer size is 10, width specification is 9
缓冲区大小包括终止空值。您可以使用宽度规范字段来确保读入的令牌适合缓冲区。如果没有使用宽度规范字段,并且读入的令牌太大而无法放入缓冲区,则不会向该缓冲区写入任何内容。
笔记
size 参数的类型是unsigned
,而不是size_t
。
该_countof()
运算符是 Microsoft 扩展。它大约等价于,在这种情况下,它与根据定义的sincesizeof(s) / sizeof(s[0])
相同。sizeof(s)
sizeof(char) == 1
请注意, size 参数是unsigned
,而不是size_t
您所期望的。这是TR 24731-1功能的 Microsoft 实施与 ISO/IEC 9899:2011 的附件 K 之间的差异领域之一。标准中指定的尺寸在技术上是rsize_t
,但它被定义为size_t
具有限制范围(因此是r
):
type is rsize_t
which is type size_t
。
但脚注(未显示)指的是 的定义RSIZE_MAX
。
另请参阅您是否使用 TR 24731 的“安全”功能?
修复问题中的代码
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()
而不是仅仅假设它有效,并且报告了标准错误的错误。