scanf是否保证不会在失败时更改值?

M.M*_*M.M 6 c scanf language-lawyer

如果scanf族函数无法与当前说明符匹配,是否允许写入存储成功值的存储?

在我的系统上,以下输出213两次但是有保证吗?

标准中的语言(C99或C11)似乎没有明确指出原始值应保持不变(无论是否不确定).

#include <stdio.h>

int main()
{
    int d = 213;

    // matching failure
    sscanf("foo", "%d", &d);
    printf("%d\n", d);

    // input failure
    sscanf("", "%d", &d);
    printf("%d\n", d);
}
Run Code Online (Sandbox Code Playgroud)

Pas*_*uoq 5

C11标准的相关部分是(7.21.6.2,对于fscanf):

7作为转换规范的指令定义了一组匹配的输入序列,如下面针对每个说明符所述.转换规范按以下步骤执行:

8 [...]

9除非规范包含n说明符,否则从流中读取输入项.输入项被定义为输入字符的最长序列,其不超过任何指定的字段宽度,并且是匹配输入序列的前缀,或者是匹配输入序列的前缀.285)输入项之后的第一个字符(如果有)仍未读.如果输入项的长度为零,则指令的执行失败; 除非文件结束,编码错误或读取错误阻止了流的输入,否则此条件是匹配失败,在这种情况下,它是输入失败.

10除了%说明符之外,输入项(或者,在%n指令的情况下,输入字符的数量)将转换为适合转换说明符的类型.如果输入项不是匹配序列,则指令的执行失败:此条件是匹配失败.除非通过*指示赋值抑制,否则转换的结果将放在由尚未收到转换结果的format参数后面的第一个参数指向的对象中.[...]

对我来说,单词"step"和"如果输入项的长度为零,指令的执行失败"表示如果输入与格式中的说明符不匹配,则解释在该说明符的任何赋值之前停止发生了.


另一方面,关于引用的子条款4清楚地说明了指定失败者的说明符,再次使用适合于有序事件序列的语言:

4 fscanf函数依次执行格式的每个指令.当所有指令都已执行,或者指令失败时(如下所述),函数返回.

  • 在至少一种情况下,我认为`scanf`几乎**必须**修改指向存储,即使指令失败:对于`%c`指令,它需要完全'n`字符,其中`n`是请求的字段宽度,而不仅仅是最新的字符.在这种情况下,如果`n`很大且文件不可搜索,则在存储到目标缓冲区之前无法事先知道指令是成功还是失败.不过我不同意你的第一个解释.这可能是委员会应该提出的一个缺陷...... (3认同)
  • @mafso:我说不清楚标准是否允许这种情况发生,尽管没有其他方法可以实现它.请注意,对于`%s`和`%[`,只有在没有读取字符时才会发生匹配失败,在这种情况下,实现没有理由将任何内容写入缓冲区.但是'%c`的预期形式具有确切的字符数(如果允许读取的次数较少,则调用者无法确定成功读取的数量),因此如果早期发现EOF,则会发生匹配失败. (2认同)