在使用字符串数组时使用 scanf_s 的正确方法是什么?

What's the correct way to use scanf_s in using string arrays?

char array1[10];
scanf_s("%9s", array1, (unsigned)_countof(array1);

(unsigned)_countof(array1)是什么意思?

与使用 scanf_s("%9s", array1, sizeof(array1); 有何不同?

都有效,但我想更确切地了解它

这道题是基于编译器的,GCC 11.1.0 on Arch Linux没有scanf_s_countof这样的函数。这些 functions/macros 可能在 Windows.

中有效

我在 Microsoft docs 上阅读了一些文档。因此,_countof 是一个在内部调用 sizeof() 的宏,而 scanf_s 类似于标准 C17 中的 scanf

What's mean of (unsigned)_countof(array1)? and what's different from use scanf_s("%9s", array1, sizeof(array1);? both work, but I want to understand about it more surely

此处宏 _countof 正在计算 stack 存储数组的长度,在本例中为 10.

_countof 宏扩展为:

#define _countof(x) (sizeof(x) / sizeof(x[0]))
// the operation goes for `array1` like this:
// 10 * 1 byte / 1 byte
// 1 byte is the sizeof char
// hence, 10 is returned as the result of the above operation

(unsigned)只是对上述操作的值进行类型转换。

注意:由于 _countof 正在调用 sizeof(),因此不要在获取数组长度的函数中使用它。因为 sizeof(arr_ptr) 将 return 指针的大小,在我的例子中是 8 字节(x86_64 架构).

结论:

没有 _countof 正在调用 sizeof()。我想建议您使用 sizeofscanf 函数,因为它们 cross-platform 并且在整个 C 标准中都是可移植的。

sizeof_countof是不同的。 (编辑:)在这种情况下,您应该使用 countof.

sizeof是C语言中的一个运算符,return是一个变量占用的内存大小,以字节为单位。 在本例中,array1 是一个包含 10 个字符的数组,因此它的大小是 char 大小的十倍,而 sizeof(char) 是 1 个字节。所以sizeof(array1)的值为10 * 1 = 10个字节。

请注意,在 C 中,您可以对任何变量(例如 sizeof(array1))或任何类型(例如 sizeof(int))使用 sizeof

_countof 是一个宏(仅在 Microsoft 平台上可用),它为您提供数组变量中声明的 个元素 。在这种情况下,您的 array1 变量有 10 个元素,因此 _countof(array1) 将为 10。

现在 在你的精确情况下 这恰好是相同的结果,因为每个 char 的大小是 1,但是如果,这就不同了,例如,您的变量是 ints.

的数组
int array2[10];

sizeof(array2);  // = 40 
_countof(array2); // = 10

int(通常)是 4 个字节,因此 10 个 int 的数组的大小为 10*4 = 40 个字节。另一方面,_countof 将只计算数组中声明了多少个元素,并且仍然 return 10.

其实我们可以看到_countof的定义就是sizeof(array)除以sizeof(array[0]),也就是单个元素的大小

由于 scanf_s"%s" 需要多个项目,您应该使用 _countof。 (编辑).

您可能还需要小心数组上的 sizeof(和 _countof),并避免在指针上使用它们。另请注意,_countof 在 Visual Studio 之外将不起作用。参见 these related answers

What's the correct way to use scanf_s in using string arrays?

scanf_s()"%9s" 不适用于 字符串数组 。它用于读取文本并保存为单个 string,它是一个 character array with a null character.

它的正确使用很复杂,因为 MSVC 期望计数参数中的类型与 C11 不同。在 C11 及以后的版本中,scanf_s() 是标准库的可选函数,没有得到广泛接受。

// MSVC - type unsigned expected, hence the cast.
scanf_s("%9s", array1, (unsigned)_countof(array1);

// C11 - type size_t expected
scanf_s("%9s", array1, sizeof array1 / sizeof array1[0]);

正确使用任一种代码都会检查 scanf_s()

的 return 值
if (1 == scanf_s("%9s", ...)) Success();
else Fail();

What's mean of (unsigned)_countof(array1)?

_countof() 是等同于 (sizeof(array) / sizeof(array[0])) 的 MSVC 宏。当传递一个数组时,它 return 是数组中元素的计数,类型为 size_t。与 MSVC scanf_s() 一样,转换为 unsigned 会得到预期的类型。由于强制转换,该值可能会被截断 - 大型数组的罕见问题。


what's different from use scanf_s("%9s", array1, sizeof(array1));?

sizeof(array1) 的预期类型是 size_t 而不是 MSVC 中预期的 unsigned - 导致 未定义的行为 。当 size_tunsigned 一样时,没关系,否则就是真正的问题。

概念值错误。应该是数组元素count,而不是数组的字节size。此处作为 sizeof(char)==1 可以,但如果代码移动到使用宽字符则错误。


both worked

代码不可移植。它可能在 OP 的情况下“有效”,但缺乏可移植性。


考虑 scanf_s(), scanf() 的替代方案,例如 fgets()