gpt4 book ai didi

c - %ms 和 %s scanf 之间的区别

转载 作者:行者123 更新时间:2023-11-30 16:47:42 36 4
gpt4 key购买 nike

阅读 scanf 手册时我遇到了这一行:

An optional 'm' character. This is used with string conversions(%s, %c, %[),

有人可以用简单的例子来解释一下它的区别以及在某些情况下这种选项的需要吗?

最佳答案

C 标准在 scanf() 中没有定义这样的可选字符。格式。

GNU lib C 确实定义了一个可选的 a这样指示(来自 scanf 的手册页):

An optional a character. This is used with string conversions, and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead, scanf() allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to a char * variable (this variable does not need to be initialized before the call).

The caller should subsequently free this buffer when it is no longer required. This is a GNU extension; C99 employs the a character as a conversion specifier (and it can also be used as such in the GNU implementation).

手册页的注释部分显示:

The a modifier is not available if the program is compiled with gcc -std=c99 or gcc -D_ISOC99_SOURCE (unless _GNU_SOURCE is also specified), in which case the a is interpreted as a specifier for floating-point numbers (see above).

Since version 2.7, glibc also provides the m modifier for the same purpose as the a modifier. The m modifier has the following advantages:

  • It may also be applied to %c conversion specifiers (e.g., %3mc).

  • It avoids ambiguity with respect to the %a floating-point conversion specifier (and is unaffected by gcc -std=c99 etc.)

  • It is specified in the upcoming revision of the POSIX.1 standard.

在线 Linux 手册页 http://linux.die.net/man/3/scanf仅将此选项记录为:

An optional 'm' character. This is used with string conversions (%s, %c, %[), and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead, scanf() allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to a char * variable (this variable does not need to be initialized before the call). The caller should subsequently free(3) this buffer when it is no longer required.

Posix 标准在其 POSIX.1-2008 版本中记录了此扩展(请参阅 http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html ):

The %c, %s, and %[ conversion specifiers shall accept an optional assignment-allocation character m, which shall cause a memory buffer to be allocated to hold the string converted including a terminating null character. In such a case, the argument corresponding to the conversion specifier should be a reference to a pointer variable that will receive a pointer to the allocated buffer. The system shall allocate a buffer as if malloc() had been called. The application shall be responsible for freeing the memory after usage. If there is insufficient memory to allocate a buffer, the function shall set errno to [ENOMEM] and a conversion error shall result. If the function returns EOF, any memory successfully allocated for parameters using assignment-allocation character m by this call shall be freed before the function returns.

使用此扩展,您可以编写:

char *p;
scanf("%ms", &p);

导致scanf从标准输入解析单词并分配足够的内存来存储其字符以及终止 '\0' 。指向已分配数组的指针将存储到p中。和scanf()将返回1 ,除非无法从 stdin 读取非空白字符.

其他系统完全有可能使用 m对于类似的语义或完全不同的东西。非标准扩展是不可移植的,在标准方法麻烦、不切实际或完全不可能的情况下,应该非常小心地使用,并记录下来。

请注意,使用 scanf() 的标准版本确实不可能解析任意大小的单词。 :

您可以解析具有最大大小的单词,并且应指定在'\0'之前存储的最大字符数。 :

char buffer[20];
scanf("%19s", buffer);

但这并不能告诉您在标准输入中还有多少个字符可供解析。无论如何,如果输入足够长,不传递最大字符数可能会引发未定义的行为,并且攻击者甚至可能使用特制的输入来危害您的程序:

char buffer[20];
scanf("%s", buffer); // potential undefined behavior,
// that could be exploited by an attacker.

关于c - %ms 和 %s scanf 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43237996/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com