Какой заполнитель я должен использовать и почему?

0

Почему код работает только тогда, когда я использую заполнитель% lf или% f (второй заполнитель), но он выводит 0, когда я использую% d?

#include <stdio.h>

void main()
{

    long id;
    id = 123456789;
    double Hourly;
    Hourly = 30;
    int HoursAday, daysAweek, Fired, Hired;
    HoursAday = 8; daysAweek = 5; Fired = 2021; Hired = 2019;
    printf("bob, id: \"%d\" should get %lf", id, (Hourly * HoursAday * daysAweek) * (Fired - Hired));

10
  • 2
    %dдля intценностей. %lf%fтолько для printf) для doubleзначений. Это должно было быть объяснено в любой достойной книге, классе или учебнике. Несоответствие спецификатора формата и типа значения аргумента приводит к неопределенному поведению . 2 дня назад
  • 1
    void main() должно быть int main()
    Kevin
    2 дня назад
  • 2
    @Matthieu: Потому что C 2018 5.1.2.2.1 1 говорит: «Функция, вызываемая при запуске программы, имеет имя main. Реализация не объявляет прототипа для этой функции. Он должен быть определен с возвращаемым типом intи без параметров:… »Тот факт, что компилятор, с которым вы тестировали, принял это, не означает, что другие компиляторы будут это делать, или даже что ваш компилятор примет его с другими переключателями или даже что программы с void main()кроме того, который вы пробовали, будет работать. 2 дня назад
  • 1
    @Matthieu См stackoverflow.com/questions/204476/... . В C ++ он более строгий, но все же в C вы должны использовать int main()илиint main(int, char**)
    Kevin
    2 дня назад
  • 2
    Даже код как есть должен жаловаться на несоответствие форматирования первого аргумента, не говоря уже о втором . Компиляция с включенными предупреждениями. Всегда.
    Cheatah
    2 дня назад
3

Тип (Hourly * HoursAday * daysAweek) * (Fired - Hired)является doubleнастолько правильным спецификатор %lf. Из-за преобразований по умолчанию с переменными аргументами код также будет работать с %f(*). Но %dэто неопределенное поведение.

Кроме того, правильный спецификатор для id(который имеет тип long) - это %ld. %dнеопределенное поведение.

См. Документацию для printf: https://en.cppreference.com/w/c/io/fprintf

(*) floatАргумент с переменным числом аргументов всегда преобразуется в double. Таким образом, printfсемейство функций никогда не получит float, они всегда будут получать double. Вот почему %fи %lfпо практическим причинам эквивалентны.

2

Это выражение

(Hourly * HoursAday * daysAweek) * (Fired - Hired)

имеет тип doubleиз-за обычных арифметических преобразований, потому что переменная Hourlyимеет тип double. То есть, если один операнд имеет тип, doubleа другой операнд имеет целочисленный тип в двоичной операции, тогда операнд с целочисленным типом преобразуется в тип double.

Использование неправильного спецификатора преобразования, %dпредназначенного для вывода объектов типа intс объектом этого типа, doubleвызывает неопределенное поведение.

Обратите внимание, что в этом спецификаторе преобразования %lfмодификатор длины lне действует. Так что достаточно использовать %f.