scanf("%d%d",&x,&x)是否定义良好?

chu*_*ica 15 c restrict language-lawyer

以下代码是否定义良好?

#include <stdio.h>

int ScanFirstOrSecond(const char *s, int *dest) {
    return sscanf(s, "%d%d", dest, dest);
}

int main(void) {
    int x = 4;
    ScanFirstOrSecond("5", &x);
    printf("%d\n", x);  // prints 5

    // Here is the tricky bit
    ScanFirstOrSecond("6 7", &x);
    printf("%d\n", x);  // prints 7
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

换句话说,这些...论点是否暗示restrict了它们?

我发现最适用的C规范是

fscanf函数依次执行格式的每个指令.......C11dr§7.21.6.24

chq*_*lie 11

简短的回答是:是的,定义如下:

scanf将尝试将一个字节序列转换stdin为基数为10的整数,并带有可选的初始空格和一个可选的符号.如果成功,该号码将被存储x.scanf然后将再次执行这些步骤.返回值可以是EOF,0,12,对于后者2,转换的最后一个号码将已被存入x.

冗长的答案有点夸张:

似乎C标准确实指定值以格式字符串的顺序存储.引用C11标准:

7.21.6.2 fscanf功能

...

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

...

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

...

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

...

16 如果在第一次转换(如果有)完成之前发生输入故障,该fscanf函数将返回宏的值EOF.否则,该函数返回分配的输入项的数量,如果早期匹配失败,则可以少于提供的数量,甚至为零.

本规范中的任何其他地方都没有对提到的输出对象的任何访问.

然而,标准的措辞似乎表明,如果2个指针指向同一个对象,则行为可能是意外的:转换的结果放在第一个参数指向的对象之后,该参数在格式参数之后尚未收到转换结果. 这句话有些含糊不清:尚未收到转换结果的是什么?对象或论点?对象接收转换结果,而不是指针参数.在您的扭曲示例中,对象x已经收到了转换结果,因此它不应该接收另一个...但正如supercat所指出的,这种解释具有明显的限制性,因为它意味着所有转换后的值都存储在第一个目标对象中.

因此,它看起来完全明确并且定义明确,但可以完善规范的措辞以消除潜在的歧义.

  • 答案的关键要素:**依次执行格式的每个指令**和**转换的结果放在第一个参数指向的对象中......**.与[@Seb](http://stackoverflow.com/questions/35712349/is-scanfdd-xx-well-defined#comment59110660_35712752)一起注释它是参数顺序(而不是值),指出这是规范结论结果需要明确定义. (2认同)