【发布时间】:2013-05-29 16:06:57
【问题描述】:
如何使用 0 的 scanf 宽度说明符?
1) 不受限制的宽度(如 cywin gcc 版本 4.5.3 所示)
2) UB
3)别的东西?
我的应用程序(未显示)动态地将宽度说明符作为 scanf() 的较大格式字符串的一部分。它很少会在格式字符串的中间创建一个"%0s"。在这种情况下,%0s 的目标字符串只有 1 个字节的空间供 scanf() 存储 \0,上面的行为 #1 会导致问题。
注意:以下测试用例使用常量格式。
#include <memory.h>
#include <stdio.h>
void scanf_test(const char *Src, const char *Format) {
char Dest[10];
int NumFields;
memset(Dest, '\0', sizeof(Dest)-1);
NumFields = sscanf(Src, Format, Dest);
printf("scanf:%d Src:'%s' Format:'%s' Dest:'%s'\n", NumFields, Src, Format, Dest);
}
int main(int argc, char *argv[]) {
scanf_test("1234" , "%s");
scanf_test("1234" , "%2s");
scanf_test("1234" , "%1s");
scanf_test("1234" , "%0s");
return 0;
}
输出:
scanf:1 Src:'1234' Format:'%s' Dest:'1234'
scanf:1 Src:'1234' Format:'%2s' Dest:'12'
scanf:1 Src:'1234' Format:'%1s' Dest:'1'
scanf:1 Src:'1234' Format:'%0s' Dest:'1234'
我的问题是关于最后一行。似乎 0 宽度导致没有宽度限制,而不是 0 宽度。如果这是正确的行为或 UB,我将不得不以另一种方式处理零宽度情况,或者是否有其他 scanf() 格式需要考虑?
【问题讨论】:
-
看起来
%0s被评估为%s。 0 被忽略。但我无法确认。我不知道是否有标准提及这种行为 -
有一个
*格式规范来禁止分配。这会有帮助吗? -
@mf_ UB 代表未定义的行为。
-
@Arkadiy
*抑制赋值的格式规范是一个新颖的想法。它会阻止 0 宽度的目标字符串接收数据,但不幸的是,scanf()仍然会消耗输入字符串,不会为下一个地址不在正确位置的格式说明符留下任何内容。