Хроники Города Глупова - Какая, однако, сволочь... (или, век живи, век учись, часть 298734)
April 13th, 2004
02:43 pm

[Link]

Previous Entry Add to Memories Tell A Friend Next Entry
Какая, однако, сволочь... (или, век живи, век учись, часть 298734)
Как оказалось, в ситуации

double a;

.......


fprintf(stdout, "%i\n", a);

Компилятор Borland 3.1 C++ (ретрокомпутинг, ага) автоматически каст не делает. Надо

fprintf(stdout, "%i\n", (int)a);


Ну кто бы мог подумать. Хорошо, пишет нули там где их быть не должно, а не всякую чепуху.

Много думал.

UPDATE: разумеется, имелось ввиду не %i, a %d. до цчего английский доводит...

(13 comments | Leave a comment)

Comments
 
[User Picture]
From:[info]diamond_age@lj
Date:April 13th, 2004 - 03:24 pm
(Link)
В этой ситуации ни один компилятор кастов делать не будет, ибо для этого надо распарсить форматную строку. А для этого надо знать детали реализации fprintf, что ему западло -- не компилятора это дело. Вообще в С есть общее правило, как передаются аргументы -- long передается как long; int, short, char -- как int; float, double -- как double. И именно в таком виде они и попадают в стек к fprintf и иже с ним. Чтобы компилятор сделал автоматический каст, надо, чтобы был прототип функции, а он у семейства fprintf заканчивается многоточием => нет знания о том, что каст необходим.
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 01:33 am
(Link)
Чтобы компилятор сделал автоматический каст, надо, чтобы был прототип функции, а он у семейства fprintf заканчивается многоточием => нет знания о том, что каст необходим.


Да, так и есть (в смысле fprintf). Видел как-то где-то, кажется, когда не полениься залезть в хедеры, а может, в книге какой. А с variable arguments я уже не возился чети-сколько, потому как надоело пересылать списки переменных на полстраницы. Поступил по-жлобски - наделал глобальных переменных.
From:[info]na_pis@lj
Date:April 13th, 2004 - 03:27 pm
(Link)
А что бы токого не случалось нужно, когда правильным компилятором пользуешся, выстукивать на клаве: "gcc -Wall "

А ещё лучше: "gcc -Wall -Werror "
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 01:29 am
(Link)
Это ж Борланд, под ДОСом.
[User Picture]
From:[info]azatiy@lj
Date:April 14th, 2004 - 02:43 am
(Link)
Есть djpp.
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 02:47 am
(Link)
Есть, я даже его поставил у себя. К сожалению, под него нет поддежки железа (у меня ADC карта с софтовой DMA поддержкой). То же самое с GPIB.
Каст легче сделать, всё-таки.
[User Picture]
From:[info]diamond_age@lj
Date:April 14th, 2004 - 04:19 am
(Link)
Да при чем здесь используемый компилятор? Все работает совершенно правильно. Компилятор не может отловить ошибку, связанную с семантикой конкретной функции. Он вообще не знает, зачем нужна fprintf и что она делает.
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 04:44 am
(Link)
Да я разве против. Просто мой комментарий относился к форматам конад в gcc, в частности, -Wall, которая заставляет вещать компилятор о всех несоответствиях. Поскольку djpp есть ГНУ-шный вариант под ДОС, то там это могло сработать. Но применять я его не стал по указанной причине.
[User Picture]
From:[info]diamond_age@lj
Date:April 14th, 2004 - 06:13 am
(Link)
Ну хрен его знает. Может быть, gcc это действительно отлавливает -- не проверял. НО! Это не дело компилятора. В этом случае он должен знать о том, что есть такое семейство *printf, о том, для чего оно предназначено, и о том, как выглядит строка формата. Это есть грубейшее нарушение одного из основных принципов C -- отвязанности библиотек от собственно языка. Компилятор не занимается вводом/выводом и прочей херней, на это есть стандартная библиотека. НО. Хоть она и стандартная, никто не мешает мне написать собственную функцию fprintf с таким же прототипом, которая при встрече "%i" будет делать что-нибудь совсем удивительное. И это будет законно.

А еще скажу -- то, что ты дожил до жизни такой, есть следствие просчета в дизайне :) Если тебе в вычислениях нужно плавающее, а для печати результата -- целое, имело смысл вместо "%i" написать "%.0f". Во-первых, нехорошо таким образом типы смешивать; во-вторых, округление в случае чего произошло бы правильно -- (int)0.999999 дает 0 -- вряд ли это то, что тебе нужно, а printf("%.0f", 0.999999) выведет "1".
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 06:31 am
(Link)
Дизайн я с 97 года переделывал раза три, каждый раз процентов на 80. Периодически добавляю новые возможности, и до сих пор работал (в этом конкретном месте) с типом long, а потом пришлось дописать некую функцию, которой нужен был double. Встал перед дилемой - либо переписывать код в 5-6 файлах, либо сделать пару-тройку кастов.
[User Picture]
From:[info]azatiy@lj
Date:April 13th, 2004 - 10:06 pm
(Link)
Ретрокомпутинг - это ассемблер.
[User Picture]
From:[info]m_ike@lj
Date:April 14th, 2004 - 05:31 am

А с какого бодуна

(Link)
... компилятор должен знать, что это int? Printf - это не часть языка, а обычная библиотечная функция, ты такую и сам можешь написать. Анализ аргументов (и соответственно, захват соответствующего количества байт из стека) делается опять же в теле функции, и в этом месте запросто мог случиться вылет на хрен всей сессии DOS (а если это в Windows 98, то и винды вместе с ней).

Вот cout<<a<<'\n'; - совсеееем другое дело, раз уж мы на ++ пишем, там оно для каждого типа отдельно перегружено, и никакого cast не надо.
From:[info]ded_mitya@lj
Date:April 14th, 2004 - 06:13 am

Re: А с какого бодуна

(Link)
Я начал писать проект давно, и писал на самом что ни есть базовом С, который, в случае чего, можно было бы перетащить под другой компилятор. Сейчас там размер кода перевалил за 10 тыс. строк, надо было, конечно, зная такой расклад, сразу лабать на плюсах...
Комиссариат Культуры Powered by LJ.Rossia.org