Можно ли передавать адрес типа int для scanf ("% x", ...)? - PullRequest
0 голосов
/ 20 сентября 2018

Определен ли beavior следующий код:

#include <stdio.h>

int main() {
    int x;
    if (scanf("%x", &x) == 1) {
        printf("decimal: %d\n", x);
    }
    return 0;
}

clang компилирует его без каких-либо предупреждений даже со всеми включенными предупреждениями, включая -pedantic.Стандарт C кажется однозначным по этому поводу:

C17 7.21.6.2 fscanf функция

...

...результат преобразования помещается в объект, на который указывает первый аргумент, следующий за аргументом формата, который еще не получил результат преобразования.Если этот объект не имеет подходящего типа или если результат преобразования не может быть представлен в объекте, поведение не определено.

...

Спецификаторы преобразования и их значенияявляются:

...

x Сопоставляет необязательное шестнадцатеричное целое число со знаком, формат которого совпадает с ожидаемым для предметной последовательности функции strtoul со значением 16для аргумента base.Соответствующий аргумент должен быть указателем на целое число без знака.

На двух дополнительных архитектурах преобразование -1 с %x, кажется, работает, но это не сработает в древних знаковых / магнитудных или одних системах дополнения..

Есть ли какое-либо положение, чтобы определить это поведение или, по крайней мере, определить реализацию?

1 Ответ

0 голосов
/ 20 сентября 2018

Это относится к категории поведений, которые должны поддерживать реализации качества, если только они не документируют веские причины для других действий, но которые Стандарт не предписывает.Авторы Стандарта, похоже, воздерживаются от попыток перечислить все такие варианты поведения, и для этого есть как минимум три веские причины:

  1. Это сделало бы Стандарт дольше, итратя чернила, описывающие очевидное поведение, которое читатели ожидают в любом случае, отвлечет от тех мест, где Стандарт должен привлечь внимание читателей к вещам, которых они не могли бы ожидать иначе.

  2. Авторы Стандартавозможно, не хотел исключать возможность того, что у реализации может быть веская причина сделать что-то необычное.Я не знаю, было ли это соображением в вашем конкретном случае, но это могло бы быть.

    Рассмотрим, например, (вероятно, теоретическую) среду, соглашение о вызовах которой требует передачи информации о типах аргументов, передаваемых вфункции с переменным числом, которые предоставляют функцию scanf, которая проверяет эти типы аргументов и выкрикивает, если int* передается аргументу %X.Авторы Стандарта почти наверняка не знали о какой-либо такой среде [я сомневаюсь, что она когда-либо существовала], и, таким образом, они не смогут взвесить преимущества использования процедуры scanf среды и преимущества поддержки обычного поведения.Таким образом, имело бы смысл оставить такое суждение людям, которые были бы в лучшем положении, чтобы оценить затраты и выгоды каждого подхода.

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

На практике некоторые авторы компиляторов, по-видимому, рассматривают большинство ситуаций, когда Стандарт не предписывает поведение какого-либо действия, как приглашение предполагать, что код никогда не будет пытаться выполнить его, даже если все реализации, предшествующие Стандарту, вели себя согласованно.и вряд ли когда-либо будет веская причина для реализации, чтобы сделать иначе.Следовательно, использование %X для чтения int попадает в категорию поведений, которые будут надежны в реализациях, которые прилагают все усилия для совместимости с общими идиомами, но могут потерпеть неудачу в реализациях, разработчики которых придают большее значение способностиобрабатывать бесполезные программы более эффективно или в реализациях, предназначенных для работы с программами, которые могут быть подорваны такими реализациями.

...