即使它们不相同,它也总是返回 1 我想知道为什么我必须在 scanf_s 中记下缓冲区大小 如果我不这样做,scnaf_s 就不起作用
int main(void) {
char str1[30] = "push";
char str2[30] = { 0 };
scanf_s("%s", &str2,2);
int result = strcmp(str1, str2);
printf("%d\n", result);
printf("%d %d", strlen(str1), strlen(str2));
return 0;
}
比较str1和str2s的长度 我试图使用 strlen 但结果是 4 和 0 str2怎么可能是0?
它总是返回 1,即使它们不相同,我想知道为什么我必须在 scanf_s 中记下缓冲区大小,如果我不这样做的话,scnaf_s 不起作用
如果可以避免,请不要使用
scanf_s()
或微软的其他所谓的安全增强功能。它们是非标准的*,并不比它们更传统的对应物特别安全,尽管微软的断言与此相反。在这种特殊情况下,他们咬了你。硬
scanf_s
说明符时,为什么我必须将缓冲区大小传递给 %s
?因为你做。这是该功能的一个有据可查的特征。目的是它允许函数避免溢出为接收结果而提供的缓冲区。但当然,要成功做到这一点,程序员必须传递一个实际上不超过实际缓冲区大小的缓冲区长度。还有其他更好的方法来解决这个问题。
strcmp()
should 当字符串不同时返回非零值。我假设您的意思是当相同时strcmp()
返回1,但您错了。程序中的 strcmp()
调用不可能比较相等的字符串,因为被比较的字符串之一,"push"
是四个字符长,而这个 scanf_s()
调用 ...
scanf_s("%s", &str2,2);
...无论您输入什么,都不会读取超过一个字符的字符串。指定的 2 字节缓冲区大小必须容纳字符串字符和终止 null。
很容易。根据文档,
当令牌太大而不适合时,除非有宽度规范,否则不会将任何内容写入缓冲区。
“太大”是指相对于您传递的缓冲区大小 (2),并且您没有提供宽度规范,因此如果您尝试输入大于将适合的字符串(即大于 1 个字符;见上文)
str2
没有任何内容。您注意将其初始化为全零(对您有好处),因此第一个字符是字符串终止符——因此是零长度字符串。
如果必须使用
scanf_s
,则传递反映实际缓冲区大小(30 字节)的缓冲区大小参数。建议还包含一个宽度说明符:
char str2[30] = { 0 };
scanf_s("%29s", &str2, (unsigned int) sizeof(str2));
如果你不需要使用
scanf_s()
那么你有很多可能性。其中最好的是fgets()
:
fgets(str2, sizeof(str2), stdin);
但是你也可以使用传统的
scanf()
:
scanf_s("%29s", &str2);
请注意,在这种情况下,适当的宽度说明符(如所示)足以避免缓冲区溢出。
*Microsoft 设法将这些函数的版本作为可选附件添加到 C 语言规范中,但它们自己的实现不符合要求,而且很少有其他 C 库提供任何版本。