gpt4 book ai didi

*scanf 中 %n 运算符的一致性和行为

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

我目前正在将一些 HTTP 处理构建到 C 程序(在 Linux 上使用 glibc 编译)中,该程序将位于 nginx 实例后面,并认为我应该安全地将参数标记化推迟到 sscanf在这种情况下。
我很高兴地发现从 URI 中提取查询非常简单:

char *path = "/events?a=1&b=2&c=3";

char query[64] = {0};

sscanf(path, "%*[^?]?%64s HTTP", query); // query = "a=1&b=2&c=3"
但令我惊讶的是,事情变得如此迅速
int pos = -1;
char arg[32] = {0}, value[32] = {0};

int c = sscanf(query, "%32[^=]=%32[^&]&%n", &arg, &value, &pos);
对于 a=1&b=2 的输入, 我得到 arg="a" , value="1" , c=2 , pos=4 .完美:我现在可以在 path + pos 上重新运行 sscanf得到下一个论点。为什么我在这里?
好吧,虽然 a=1&行为与上述相同, a=1生产 arg="a" , value="1" , c=2 , 和 pos=-1 .我该怎么办?
争夺文档,我读到了
       n      Nothing  is expected; instead, the number of characters consumed
thus far from the input is stored through the next pointer,
which must be a pointer to int. This is not a conversion and
does not increase the count returned by the function. The as‐
signment can be suppressed with the * assignment-suppression
character, but the effect on the return value is undefined.
Therefore %*n conversions should not be used.
其中超过 50% 的段落是指簿记细节。没有讨论我所看到的行为。
在谷歌搜索结果中徘徊,我很快找到了维基百科条目 Scanf_format_string (这是 HitTest 门的),但是,呃...
format specification is empty as of June 2020
Oookay...我觉得我在这里使用了一个没有人真正关注的功能。这并没有激发我剩余的信心。
看看似乎是什么 where %n is implemented in vfscanf-internal.c ,我发现 60% 的代码(行)涉及关于标准不一致的讨论,39.6% 是实现细节,0.4% 是实际代码(由“ done++;”组成)。
它* 出现 * glibc 的行为是留下内部值 done (我使用 %n 访问)未触及 - 或者更确切地说,未定义 - 除非某些操作更改它。似乎还使用 %n以这种方式是无法预料的,​​而且我完全处于“这里有龙”的领域? :(
我不认为我会使用 scanf ...
为了完整起见,这里总结了我所看到的内容。
#include <stdio.h>

void test(const char *str) {
int pos = -1;
char arg[32] = {0}, value[32] = {0};
int c = sscanf(str, "%32[^=]=%32[^&]&%n", (char *)&arg, (char *)&value, &pos);
printf("\"%s\": c=%d arg=\"%s\" value=\"%s\" pos=%d\n", str, c, arg, value, pos);
}

int main() {
test("a=1&b=2"); // "a=1&b=2": c=2 arg="a" value="1" pos=4
test("a=1&"); // "a=1&": c=2 arg="a" value="1" pos=4
test("a=1"); // "a=1": c=2 arg="a" value="1" pos=-1
}

最佳答案

我认为 C 标准保证了 pos 的值在你的例子中保持不变。
C17 7.21.6.2 说,描述 fscanf :

(4) The fscanf function executes each directive of the format in turn. When all directives have beenexecuted, or if a directive fails (as detailed below), the function returns. Failures are described asinput failures (due to the occurrence of an encoding error or the unavailability of input characters),or matching failures (due to inappropriate input).

[...]

(6) A directive that is an ordinary multibyte character is executed by reading the next characters of thestream. If any of those characters differ from the ones composing the directive,the directive fails andthe differing and subsequent characters remain unread. Similarly, if end-of-file, an encoding error,or a read error prevents a character from being read, the directive fails.


(这里的“多字节字符”包括普通的单字节字符,例如您的 & 。)
所以在您的 "a=1"例如,指令 %32[^=] , = , 和 %32[^&]一切都成功了,现在已经到了字符串的末尾。在 7.21.6.7 中解释了对于 sscanf , "到达字符串的末尾等价于
遇到 fscanf 函数的文件尾。”因此无法读取任何字符,因此 & 指令失败,并且 sscanf 返回而没有做任何进一步的操作。 %n 指令从未执行过,因此没有发生任何事情将有权修改 pos 的值。因此它必须具有与之前相同的值,即 -1。
我不认为这个案子是不可预见的;只是它已经被现有规则所涵盖,所以没有人费心去明确地指出它。

关于*scanf 中 %n 运算符的一致性和行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62630442/

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