Существует ли гарантированный порядок назначения в scanf? - PullRequest
2 голосов
/ 01 мая 2019

Я наткнулся на какой-то код, и мне было интересно, было ли это просто случайностью, что он работал, как ожидалось, или это просто плохая практика. Рассмотрим следующий 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. Я нет.

1 Ответ

3 голосов
/ 01 мая 2019

Вы не видели упоминания в N4810, потому что когда речь идет о стандартной библиотеке C, спецификация в основном откладывается до "ISO / IEC 9899: 2011, Языки программирования - C" .Если мы посмотрим на N1570 (черновик C11), то это говорит о семействе функций scanf:

7.21.6.2 Функция fscanf (выделение мое)

10 За исключением случая, когда указан спецификатор%, элемент ввода (или, в случае директивы% n, количество вводимых символов) преобразуетсяк типу, соответствующему спецификатору преобразования.Если элемент ввода не совпадает с последовательностью, выполнение директивы завершается неудачно: это условие является ошибкой совпадения.Если подавление присваивания не было указано *, результат преобразования помещается в объект, на который указывает первый аргумент, следующий за аргументом формата, который еще не получил результат преобразования. Если этот объект не имеет соответствующего типа , или если результат преобразования не может быть представлен в объекте, поведение не определено .

Таким образом, ваш пример работы действительно случайность, рожденная из неопределенного поведения.

...