Хроники Города Глупова - Какая, однако, сволочь... (или, век живи, век учись, часть 298734)
[Recent Entries][Archive][Friends][User Info]
02:43 pm
[Link] |
Какая, однако, сволочь... (или, век живи, век учись, часть 298734) Как оказалось, в ситуации
double a;
.......
fprintf(stdout, "%i\n", a);
Компилятор Borland 3.1 C++ (ретрокомпутинг, ага) автоматически каст не делает. Надо
fprintf(stdout, "%i\n", (int)a);
Ну кто бы мог подумать. Хорошо, пишет нули там где их быть не должно, а не всякую чепуху.
Много думал.
UPDATE: разумеется, имелось ввиду не %i, a %d. до цчего английский доводит...
|
|
|
В этой ситуации ни один компилятор кастов делать не будет, ибо для этого надо распарсить форматную строку. А для этого надо знать детали реализации fprintf, что ему западло -- не компилятора это дело. Вообще в С есть общее правило, как передаются аргументы -- long передается как long; int, short, char -- как int; float, double -- как double. И именно в таком виде они и попадают в стек к fprintf и иже с ним. Чтобы компилятор сделал автоматический каст, надо, чтобы был прототип функции, а он у семейства fprintf заканчивается многоточием => нет знания о том, что каст необходим.
Чтобы компилятор сделал автоматический каст, надо, чтобы был прототип функции, а он у семейства fprintf заканчивается многоточием => нет знания о том, что каст необходим.
Да, так и есть (в смысле fprintf). Видел как-то где-то, кажется, когда не полениься залезть в хедеры, а может, в книге какой. А с variable arguments я уже не возился чети-сколько, потому как надоело пересылать списки переменных на полстраницы. Поступил по-жлобски - наделал глобальных переменных.
А что бы токого не случалось нужно, когда правильным компилятором пользуешся, выстукивать на клаве: "gcc -Wall "
А ещё лучше: "gcc -Wall -Werror "
Это ж Борланд, под ДОСом.
Есть, я даже его поставил у себя. К сожалению, под него нет поддежки железа (у меня ADC карта с софтовой DMA поддержкой). То же самое с GPIB. Каст легче сделать, всё-таки.
Да при чем здесь используемый компилятор? Все работает совершенно правильно. Компилятор не может отловить ошибку, связанную с семантикой конкретной функции. Он вообще не знает, зачем нужна fprintf и что она делает.
Да я разве против. Просто мой комментарий относился к форматам конад в gcc, в частности, -Wall, которая заставляет вещать компилятор о всех несоответствиях. Поскольку djpp есть ГНУ-шный вариант под ДОС, то там это могло сработать. Но применять я его не стал по указанной причине.
Ну хрен его знает. Может быть, gcc это действительно отлавливает -- не проверял. НО! Это не дело компилятора. В этом случае он должен знать о том, что есть такое семейство *printf, о том, для чего оно предназначено, и о том, как выглядит строка формата. Это есть грубейшее нарушение одного из основных принципов C -- отвязанности библиотек от собственно языка. Компилятор не занимается вводом/выводом и прочей херней, на это есть стандартная библиотека. НО. Хоть она и стандартная, никто не мешает мне написать собственную функцию fprintf с таким же прототипом, которая при встрече "%i" будет делать что-нибудь совсем удивительное. И это будет законно.
А еще скажу -- то, что ты дожил до жизни такой, есть следствие просчета в дизайне :) Если тебе в вычислениях нужно плавающее, а для печати результата -- целое, имело смысл вместо "%i" написать "%.0f". Во-первых, нехорошо таким образом типы смешивать; во-вторых, округление в случае чего произошло бы правильно -- (int)0.999999 дает 0 -- вряд ли это то, что тебе нужно, а printf("%.0f", 0.999999) выведет "1".
Дизайн я с 97 года переделывал раза три, каждый раз процентов на 80. Периодически добавляю новые возможности, и до сих пор работал (в этом конкретном месте) с типом long, а потом пришлось дописать некую функцию, которой нужен был double. Встал перед дилемой - либо переписывать код в 5-6 файлах, либо сделать пару-тройку кастов.
Ретрокомпутинг - это ассемблер.
![[User Picture]](http://lj.rossia.org/userpic/4746/2147485849) | From: | m_ike@lj |
Date: | April 14th, 2004 - 05:31 am |
---|
| | А с какого бодуна | (Link) |
|
... компилятор должен знать, что это int? Printf - это не часть языка, а обычная библиотечная функция, ты такую и сам можешь написать. Анализ аргументов (и соответственно, захват соответствующего количества байт из стека) делается опять же в теле функции, и в этом месте запросто мог случиться вылет на хрен всей сессии DOS (а если это в Windows 98, то и винды вместе с ней).
Вот cout<<a<<'\n'; - совсеееем другое дело, раз уж мы на ++ пишем, там оно для каждого типа отдельно перегружено, и никакого cast не надо.
| | Re: А с какого бодуна | (Link) |
|
Я начал писать проект давно, и писал на самом что ни есть базовом С, который, в случае чего, можно было бы перетащить под другой компилятор. Сейчас там размер кода перевалил за 10 тыс. строк, надо было, конечно, зная такой расклад, сразу лабать на плюсах... |
|