scanf("%d%d", &x, &x) 定义明确吗?
Is scanf("%d%d", &x, &x) well defined?
下面的代码定义的好吗?
#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;
}
换句话说,...
参数是否隐含了 restrict
?
我找到的最适用的 C 规范是
The fscanf function executes each directive of the format in turn. ... C11dr §7.21.6.2 4
是的,定义明确。意思是"read the first token into *dest, then read the second token into *dest again"。这很奇怪但合法。
是的,因为 sscanf() 以严格的顺序执行格式字符串中的指令。
简短的回答是:是的,它被定义了:
scanf
将尝试将 stdin
中的字节序列转换为以 10 为底的整数,带有可选的初始空格和可选的符号。如果成功,号码将存入x
。 scanf
将再次执行这些步骤。 return 的值可以是 EOF
、0
、1
或 2
,对于后 2 个,最后转换的数字将存储到 x
.
长答案更微妙:
C 标准似乎确实指定值按格式字符串的顺序存储。引用 C11 标准:
7.21.6.2 The fscanf
function
...
4 The fscanf
function executes each directive of the format in turn. When all directives have been executed, or if a directive fails (as detailed below), the function returns.
...
7 A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:
...
10 Except in the case of a %
specifier, the input item (or, in the case of a %n
directive, the count of input characters) is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a *
, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result.
...
16 The fscanf
function returns the value of the macro EOF
if an input failure occurs before the first conversion (if any) has completed. Otherwise, the 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.
本规范中的任何其他地方都没有提到对输出对象的任何访问。
然而标准的措辞似乎表明,如果 2 个指针指向同一个对象,行为可能是意外的:转换的结果放在第一个指向的对象中格式参数后面的参数尚未收到转换结果。 这句话有点含糊:尚未收到转换结果 指的是什么?对象还是参数?对象接收转换结果,而不是指针参数。在你扭曲的例子中,对象 x
已经收到一个转换结果,所以它不应该再收到一个......但是正如 supercat 所指出的,这种解释是明显的限制,因为它意味着所有转换的值都被存储进入第一个目标对象。
所以它看起来完全指定且定义明确,但可以完善规范的措辞以消除潜在的歧义。
scanf()
系列函数严格依次执行您在格式字符串中留下的指令。所以第一个值将被读入,然后是第二个值,覆盖第一个。这里没有 UB。
下面的代码定义的好吗?
#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;
}
换句话说,...
参数是否隐含了 restrict
?
我找到的最适用的 C 规范是
The fscanf function executes each directive of the format in turn. ... C11dr §7.21.6.2 4
是的,定义明确。意思是"read the first token into *dest, then read the second token into *dest again"。这很奇怪但合法。 是的,因为 sscanf() 以严格的顺序执行格式字符串中的指令。
简短的回答是:是的,它被定义了:
scanf
将尝试将 stdin
中的字节序列转换为以 10 为底的整数,带有可选的初始空格和可选的符号。如果成功,号码将存入x
。 scanf
将再次执行这些步骤。 return 的值可以是 EOF
、0
、1
或 2
,对于后 2 个,最后转换的数字将存储到 x
.
长答案更微妙:
C 标准似乎确实指定值按格式字符串的顺序存储。引用 C11 标准:
7.21.6.2 The
fscanf
function...
4 The
fscanf
function executes each directive of the format in turn. When all directives have been executed, or if a directive fails (as detailed below), the function returns....
7 A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:
...
10 Except in the case of a
%
specifier, the input item (or, in the case of a%n
directive, the count of input characters) is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a*
, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result....
16 The
fscanf
function returns the value of the macroEOF
if an input failure occurs before the first conversion (if any) has completed. Otherwise, the 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.
本规范中的任何其他地方都没有提到对输出对象的任何访问。
然而标准的措辞似乎表明,如果 2 个指针指向同一个对象,行为可能是意外的:转换的结果放在第一个指向的对象中格式参数后面的参数尚未收到转换结果。 这句话有点含糊:尚未收到转换结果 指的是什么?对象还是参数?对象接收转换结果,而不是指针参数。在你扭曲的例子中,对象 x
已经收到一个转换结果,所以它不应该再收到一个......但是正如 supercat 所指出的,这种解释是明显的限制,因为它意味着所有转换的值都被存储进入第一个目标对象。
所以它看起来完全指定且定义明确,但可以完善规范的措辞以消除潜在的歧义。
scanf()
系列函数严格依次执行您在格式字符串中留下的指令。所以第一个值将被读入,然后是第二个值,覆盖第一个。这里没有 UB。