gpt4 book ai didi

c - sscanf 是否需要以空字符结尾的字符串作为输入?

转载 作者:行者123 更新时间:2023-12-03 14:40:17 26 4
gpt4 key购买 nike

最近发现的对 GTA 冗长加载时间 (1) 的解释表明 sscanf() 的许多实现调用 strlen()在他们的输入字符串上为与其他扫描函数( scanf()fscanf() ...)共享的内部例程设置上下文对象。当输入字符串很长时,这可能成为性能瓶颈。解析作为字符串加载的 10MB JSON 文件,并重复调用 sscanf()带有偏移量和 %n转换被证明是加载时间的主要原因。
我的问题是应该sscanf()甚至读取超出转换完成所需字节的输入字符串?例如,以下代码是否会调用未定义的行为:

int test(void) {
char buf[1] = { '1' };
int v;
sscanf(buf, "%1d", &v);
return v;
}
该函数应该返回 1并且不需要从 buf 读取一个以上的字节,但是是 sscanf()允许从 buf 读取超出第一个字节?

(1) JdeBP提供的引用资料:
https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/
https://news.ycombinator.com/item?id=26297612
https://github.com/biojppm/rapidyaml/issues/40

最佳答案

以下是 C 标准的相关部分:

7.21.6.7 The sscanf function Synopsis

Synopsis

#include <stdio.h>
int sscanf(const char * restrict s, const char * restrict format, ...);

Description
The sscanf function is equivalent to fscanf, except that input is obtained from a string (specified by the argument s) rather than from a stream. Reaching the end of the string is equivalent to encountering end-of-file for the fscanf function. If copying takes place between objects that overlap, the behavior is undefined.

Returns
The sscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the sscanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.


输入特指 字符串 ,所以它应该是空终止
尽管字符串中匹配转换说明符的初始前缀之外的字符以及可能帮助确定匹配序列结尾的下一个字节都没有用于转换,但这些字符后面必须跟一个空终止符,因此输入是一个格式良好的字符串,它符合调用 strlen()在它上面确定输入长度。
为了避免长输入字符串的线性时间复杂度, sscanf()应该使用 strnlen() 将字符串末尾的扫描限制为小尺寸或等效并通过适当的重新填充功能。传递一个巨大的长度并让内部例程特殊情况下的空字节是一种更好的方法。
同时,程序员应该避免将长输入字符串传递给 sscanf()并为它们的解析任务使用更专业的函数,例如 strtol() ,这也需要一个格式良好的 C 字符串,但以更保守的方式实现。这也将避免超出范围字符串表示的数字转换的潜在未定义行为。

关于c - sscanf 是否需要以空字符结尾的字符串作为输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66430071/

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