scanf 中是否有保证的分配顺序?
Is there a guaranteed order of assignment in scanf?
我遇到了一些代码,想知道它是否按预期工作只是侥幸,还是只是不好的做法。
考虑以下 MCVE (ideone):
#include <cstdio>
struct dummyStruct
{
unsigned short min[4];
unsigned short max[4];
int dummyBuffer; // This just happens to be here as a real variable in the original code, not just as a buffer.
};
int main()
{
dummyStruct db;
// Note that the size of the short is assumed to be half of that of the %d specifier
sscanf(" 123, 456, 789, 112", "%d, %d, %d, %d", db.min+0, db.min+1, db.min+2, db.min+3);
sscanf("29491, 29491, 29491, 29491", "%d, %d, %d, %d", db.max+0, db.max+1, db.max+2, db.max+3);
db.dummyBuffer = 1234;
printf("%hd, %hd, %hd, %hd\n", db.min[0], db.min[1], db.min[2], db.min[3]);
printf("%hd, %hd, %hd, %hd\n", db.max[0], db.max[1], db.max[2], db.max[3]);
printf("%d\n", db.dummyBuffer);
return 0;
}
标准保证结构的内容,还是这种未定义的行为?我在 N4810 中没有看到这一点。
或者,如果我们颠倒变量的顺序,例如
printf("%hd, %hd, %hd, %hd\n", db.min[0], db.min[2], db.min[1], db.min[3]);
db.min
的内容有保证吗?参数的顺序(从左到右)是赋值的顺序吗?另请注意,即使已定义,我也不是在问为什么这是不好的做法。我也不需要评论告诉我不要使用 scanf
。我不是。
您没有在 N4810 中看到任何提及,因为当涉及到 C 标准库时,规范大部分被推迟到 "ISO/IEC 9899:2011, Programming languages — C"。如果我们看一下 N1570(C11 草案),它是关于 scanf
的
函数族:
7.21.6.2 The fscanf function (emphasis mine)
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.
If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior
is undefined.
所以你的样本工作确实是一个未定义行为的侥幸。
我遇到了一些代码,想知道它是否按预期工作只是侥幸,还是只是不好的做法。 考虑以下 MCVE (ideone):
#include <cstdio>
struct dummyStruct
{
unsigned short min[4];
unsigned short max[4];
int dummyBuffer; // This just happens to be here as a real variable in the original code, not just as a buffer.
};
int main()
{
dummyStruct db;
// Note that the size of the short is assumed to be half of that of the %d specifier
sscanf(" 123, 456, 789, 112", "%d, %d, %d, %d", db.min+0, db.min+1, db.min+2, db.min+3);
sscanf("29491, 29491, 29491, 29491", "%d, %d, %d, %d", db.max+0, db.max+1, db.max+2, db.max+3);
db.dummyBuffer = 1234;
printf("%hd, %hd, %hd, %hd\n", db.min[0], db.min[1], db.min[2], db.min[3]);
printf("%hd, %hd, %hd, %hd\n", db.max[0], db.max[1], db.max[2], db.max[3]);
printf("%d\n", db.dummyBuffer);
return 0;
}
标准保证结构的内容,还是这种未定义的行为?我在 N4810 中没有看到这一点。 或者,如果我们颠倒变量的顺序,例如
printf("%hd, %hd, %hd, %hd\n", db.min[0], db.min[2], db.min[1], db.min[3]);
db.min
的内容有保证吗?参数的顺序(从左到右)是赋值的顺序吗?另请注意,即使已定义,我也不是在问为什么这是不好的做法。我也不需要评论告诉我不要使用 scanf
。我不是。
您没有在 N4810 中看到任何提及,因为当涉及到 C 标准库时,规范大部分被推迟到 "ISO/IEC 9899:2011, Programming languages — C"。如果我们看一下 N1570(C11 草案),它是关于 scanf
的
函数族:
7.21.6.2 The fscanf function (emphasis mine)
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. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
所以你的样本工作确实是一个未定义行为的侥幸。