2

我遇到了一些代码,想知道它是否只是一个侥幸,它按预期工作还是只是不好的做法。考虑以下 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. 我不是。

4

1 回答 1

3

您在 N4810 中没有看到任何提及,因为当涉及到 C 标准库时,该规范大多推迟到"ISO/IEC 9899:2011,编程语言 — C"。如果我们看一下N1570(C11 草案),它是这样描述scanf 函数族的:

7.21.6.2 fscanf 函数(强调我的)

10除了 % 说明符的情况外,输入项(或者,在 %n 指令的情况下,输入字符的计数)被转换为适合转换说明符的类型。如果输入项不是匹配序列,则指令执行失败:此条件为匹配失败。除非用 * 指示分配抑制,否则转换结果将放置在尚未收到转换结果的格式参数之后的第一个参数所指向的对象中。 如果此对象没有适当的类型,或者转换的结果无法在对象中表示,则行为未定义

因此,您的样本工作确实是由于未定义的行为而产生的侥幸。

于 2019-05-01T07:17:16.530 回答