Интерпретация спецификатора формата в printf("%.-1f", 34.14)

Рассмотрим следующий вызов printf():

printf("%.-1f", 34.14);

он задает отрицательное значение точности -1. Выполняя этот вызов с помощью glibc, мы получаем:

%0.-1f

это верно? Если да, то почему?

Вы отметили этого юриста по языку, но не указали версию C в вопросе и ответили цитатой из C 1999. В документации для тега C сказано, что используется последняя версия стандарта C, в настоящее время 9899:2018, если иное не указано в вопросе. Отмечая языкового юриста, вы должны точно указать, о какой версии языка вы спрашиваете. Формулировка этого правила менялась в период с 1999 по 2018 год.

Eric Postpischil 24.07.2024 01:44

@EricPostpischil: Справедливое замечание. Я ошибочно предположил, что любые изменения в printf будут только «аддитивными», т. е. новым допустимым синтаксисом, а не «отрицательными», т. е. делающими действительный синтаксис недействительным.

einpoklum 24.07.2024 10:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я считаю, что это ошибка. стандарт C (ISO/IEC 9899:1999) гласит:

§7.19.6.1

  1. Каждая спецификация преобразования обозначается символом %. После % последовательно появляются следующие символы:

    ... отрезок...

    - Необязательная точность... Точность принимает форму точки (.), за которой следует либо звездочка * (описанная ниже), либо необязательное десятичное целое число;

... отрезок...

  1. Как отмечалось выше, ширина поля или точность, или и то, и другое, могут быть обозначены звездочкой. В этом случае аргумент int предоставляет ширину или точность поля. ... Аргумент отрицательной точности принимается так, как если бы точность была опущена.

Ну, -1 — отрицательное целое число; поэтому его можно законно указать буквально в строке формата; и хотя текст, объясняющий, что делать с отрицательной заданной точностью, появляется в пункте, касающемся значений, обозначенных звездочкой, конечно, это должна быть та же логика, что и для значений, указанных буквально (точно так же, как и для ширины).

Итак, я считаю, что в этой причине значение точности следует игнорировать, а строка формата эквивалентна "%f", поэтому вывод должен быть:

34.140000

(точность по умолчанию 6)

Целочисленный аргумент точности в 5 не является частью строки, а является аргументом функции printf, например: printf("%.*f", -1, 34.14)

OfNothing 24.07.2024 01:06

@OfNothing: Действительно, но в пункте 5 указано, как интерпретировать отрицательное значение точности.

einpoklum 24.07.2024 10:31
Ответ принят как подходящий

Формулировка изменилась между C11 и C17/18. В C17/18 говорится:

§7.21.6.1 Функция fprintf
4. [...] Точность принимает форму точки (.), за которой следует либо звездочка * (описано позже), либо необязательное неотрицательное десятичное целое число; [...]

Насколько я прочитал, поведение при использовании отрицательного целого числа не определено.

Это не критическое изменение, поскольку оно не делает ранее действительные программы недействительными. Намерение никогда не заключалось в том, чтобы допускать отрицательные значения, как указано в DR220 - Определение «десятичного целого числа» / N32079:

Термин «десятичное целое число» не определен ни в Стандарте, ни в ISO 2382-1. Поэтому невозможно сказать, являются ли в каждом случае:

  • значение может быть нулевым
  • можно использовать незначащую начальную нулевую цифру
  • значение может быть отрицательным.
Предлагаемое техническое исправление

Добавьте новый абзац в 7.1.1:
[#x] Десятичное целое число — это последовательность цифр, которая может начинаться с одного или нескольких нулей, но тем не менее интерпретируется как десятичная, а не восьмеричная.

Техническое исправление

В 7.19.6.1P4, который частично гласит: «[...] или необязательное десятичное целое [...]»
измените «десятичное целое число» на «неотрицательное десятичное целое число».

Это хороший ответ, но он дополняет обсуждение C99. И если я скомпилирую с -std=c99, я все равно получу тот же результат от glibc.

einpoklum 24.07.2024 10:30

@einpoklum Вчера вечером я потратил некоторое время на поиск статьи, в которой было предложено это изменение слова, чтобы иметь возможность предоставить первоначальную мотивацию для него, но я не смог найти такую ​​статью. Я предполагаю, что это было сделано потому, что кто-то мог прийти к выводу, что вы пришли, но у него никогда не было определенного поведения. Ни одна из основных реализаций не рассматривает его как 0 в режиме до C17/18, что подтверждает мое предположение. Однако я не хотел включать это предположение в ответ.

Ted Lyngmo 24.07.2024 10:45

@einpoklum Наконец-то я нашел это. В отчете о дефекте вместо «неотрицательного» использовалось «неотрицательный», поэтому я его сначала не нашел :-)

Ted Lyngmo 24.07.2024 12:17

Я думаю, что «неотрицательное десятичное целое число» по-прежнему является ошибкой в ​​стандарте, потому что, неявно признав, что десятичное целое число может иметь знак минус, оно также допускает, что может быть знак плюс, но я не думаю, что это было предназначено для того, чтобы разрешить и определите printf("%.+1f\n", 34.14);. Вероятно, следовало бы сказать «десятичное целое число без знака» или «непустая последовательность цифр».

Eric Postpischil 25.07.2024 00:27

@EricPostpischil У меня была похожая мысль, когда я нашел отчет о дефекте. Глядя на первое предложенное исправление: «Десятичное целое число — это последовательность цифр, которая может начинаться с одного или нескольких нулей, но, тем не менее, интерпретируется как десятичная, а не восьмеричная» — для отрицательных чисел вообще нет места — но они все же нашли это. необходимо сделать это явным.

Ted Lyngmo 25.07.2024 04:05

Другие вопросы по теме

Похожие вопросы