функция с переменным числом параметров в Си, в чем косяк?

Вопросы по языкам программирования Си и С++.
arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

функция с переменным числом параметров в Си, в чем косяк?

Сообщение arthur2 » 20.02.2011 (Вс) 13:26

Функция возвращает сумму чисел:
Код: Выделить всё
double sum2( int cnt,... )
{
       va_list pArg;
       double ret = 0.0;
       va_start(pArg, cnt);
       for (; cnt; cnt--)
              ret += va_arg(pArg, double);
       va_end(pArg);
       return ret;
}
В таком варианте работает правильно.

Почему тогда в таком варианте выдает что попало?
Код: Выделить всё
float sum( int cnt,... )
{
       va_list pArg;
       float ret = 0.0f;
       va_start(pArg, cnt);
       for (; cnt; cnt--)
              ret += va_arg(pArg, float);
       va_end(pArg);
       return ret;
}

В чём косяк?
Последний раз редактировалось arthur2 20.02.2011 (Вс) 14:35, всего редактировалось 1 раз.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 13:52

Артур, ты издеваешься?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 14:06

Ага, издеваюсь. О чём ты?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 14:28

О вопросе. То, что я сейчас буду делать с твоим кодом, почему ты это сам с ним не можешь сделать?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 14:55

Хакер писал(а):О вопросе
Что не так в вопросе? Что ты всё вокруг да около?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 14:58

Хакер писал(а):То, что я сейчас буду делать с твоим кодом, почему ты это сам с ним не можешь сделать?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 15:19

Что ты будешь с ним делать? Хватит уже ходить кругами
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 15:28

То есть ты не знаешь, что делают с кодом, если он работает не правильно?

Я бы поверил в это, если бы человек сутки назад не говорил об отладке вообще и Watch-ах в частности, которые как раз ему самому сейчас нужны.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 16:15

То есть, ты думаешь, что я ничего такого не проделал? :lol: Ни какой внятной интерпретации результатов этих действий я не вывел - иначе может быть бы и не спрашивал. Но некая догадка всё-таки была: по адресу pArg оказывается не флот, а дабл.

Собственно, что и подтвердилось:
Страуструп писал(а):Очевидно, что раз параметр неописан, то транслятор не имеет сведений для контроля и стандартных преобразований типа этого параметра. Поэтому char или short передаются как int, а float как double, хотя пользователь, возможно, имел в виду другое.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 17:37

arthur2 писал(а):То есть, ты думаешь, что я ничего такого не проделал? :lol: Ни какой внятной интерпретации результатов этих действий я не вывел - иначе может быть бы и не спрашивал.

Об этом надо писать, понимаешь это? Один из популярных первых вопросов автору топику: «какие действия были проделаны». Не с проста это.

arthur2 писал(а): Но некая догадка всё-таки была: по адресу pArg оказывается не флот, а дабл.

Догадка???

Каким отладчиком ты пользовался (ты сам написал, что пользовался)?

Допустим, ты пользовался OllyDbg. Смотрим в OllyDbg как выглядит вызов функции sum, что кладётся в стек:
Изображение

Что видно? Пару push-ов на каждый float-аргумент, и того 8 байт в стеке на один float-аргумент на один float-аргумент, несмотря на TDC.

Но OllyDbg — это для брутальных парней, которые пишут на ассемблере. Нежный хрупкий сишник выберет что-то вроде MSVC++.

Хорошо, ты используешь MSVC++. Ставим брекпоинт на вызов функции sum и смотрим дизассемблинг-листинг вызова этой функции:
Изображение
Видим то же самое: для каждого float-аргумента пушится целых два dword-а. 8 байт вместо 4. Правда стековый фрейм не видно, потому что он ещё не сформирован.

Но тут ты можешь возразить: я не знаю этот чёртов ассемблер, я сишник, а смысл Си в том, чтобы писать один универсальный код под множество архитектур, не зная их ассемблера.

Хорошо, MSVC++ IDE, но не смотрим листинг дизасма, а смотрим стек:
Изображение
Что видим? У нас был int-аргумент — в стеке он представлен одним dword-ом. У нас ещё было три float-аргумента, но в стеке целых шесть dword-ов. Причём видно, что три одинаковых блока по два dword-а. Значит на каждый аргумент сохраняется 8 байтов.
Но и тут ты можешь возразить: dword составляет 4 байта на машинах с двухбайтовым словом (x86), для поиска верхушки стека мы использовали регистр esp, который характерен для x86, да и вообще смотреть дамп стека — это слишком низкоуровневые вещи для нежного сишника.

Ладно, выкрутимся из ситуации не выходя за рамки языка Си (с его хитрыми кастованиями), применим упомянутые тобою Watch-и:
Изображение

И что видим? Если трактовать аргументы, идущие вслед за cnt, как float-ы, то видим непонятные числа. Но видим также и регулярную структуру: числа хоть и непонятные, но повторяются с периодом 2 элемента. На три одинаковых аргумента приходится 3 одинаковых пары непонятных чисел. А если трактурем аргументы, идущие вслед за cnt как double-ы, то видим наше 77777.8888, с учётом потери точности FP-форматом.

Четыре разных способа проверить. О которых ты явно знаешь. Но заставляешь кого-то другого (например меня) делать это за тебя. Вот ещё вопрос: если ты говоришь, что пытался делать какую-то отладку, как ты смеешь говорить слово «догадка», когда есть 4 способа, показывающие, что это факт?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 18:02

Ух ты! Очень познавательно и - смею надеется, пригодится :)
Хакер писал(а):Четыре разных способа проверить. О которых ты явно знаешь.
ты меня явно переоцениваешь. Ну, четвертый с горем пополам ещё мог бы прийти мне в голову, но не пришел.

Но в целом - логика функции была, вроде, правильной, так что раз она выдавала какую-то лабуду, то первое, что я предположил - есть какое-то всем известное объяснение, какой-то нюанс, который я просто не учёл, но который известен и где-нибудь задокументирован. Собственно, о том и спрашивал - не предполагая, что для ответа на вопрос отладка ВООБЩЕ ПОНАДОБИТСЯ.

Кстати, вопрос в догонку. Есть такой очевидный вариант без макросов:
Код: Выделить всё
      double sum( int cnt,... )
      {
          double ret=0.0, *pArg=(double *)(&cnt+1);
       
          for (; cnt; cnt--,pArg++)ret+= *pArg;
          return ret;
      }
Я понимаю, что правильнее - с макросами, но хочется это как-то доказать. Как спровоцировать ситуацию, в которой этот код работал бы неправильно? Нужна какая-то определенная платформа? или какой-то конкретный компилятор? Какие?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 18:14

Лучше уж так:
Код: Выделить всё
      double sum(int cnt, double a, ...)
      {
          double ret=0.0;
          while(cnt > 0) ret += (&a)[--cnt];
          return ret;
      }


arthur2 писал(а):какая-то определенная платформа?

Когда величина выравнивания начал аргументов на стеке больше размера типа аргумента. Например для типов char и short это проявится и на x86.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 19:07

Хакер писал(а):Лучше уж так:
Чем лучше, ведь прототип-то получился другой :( А с индексом - прикольно :)

Хакер писал(а):Например для типов char и short это проявится и на x86
Но ведь
Страуструп писал(а):Поэтому char или short передаются как int
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 19:36

Ещё одно: может и не косяк, но всё-таки - у тебя сумма высчитывается, начиная с последних слагаемых, а не первых. А так как результаты с какой-то погрешностью, то сумма от перестановки слагаемых чуточку, но меняется.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 20:05

arthur2 писал(а):ведь прототип-то получился другой :(

Другой. Это почему-то плохо?

arthur2 писал(а):Но ведь

Что ведь? Опять взаимоисключения узрел? Вообще, что делает Страуструп к теме о Си без плюсов? :)

arthur2 писал(а):А так как результаты с какой-то погрешностью, то сумма от перестановки слагаемых чуточку, но меняется.

Насколько я чувствую этот процесс, того, что ты описываешь, не будет.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 20:51

Хакер писал(а):Насколько я чувствую этот процесс, того, что ты описываешь, не будет.
А ты думаешь, я логически это вывел? Не-а, просто так получается - чуть-чуть, но разница набегает. Причем, не всё время, а только иногда.
Хакер писал(а):Другой. Это почему-то плохо?
Плохо. Зачем функции лишний параметр? что предлагаешь в неё передавать?
Хакер писал(а):что делает Страуструп к теме о Си без плюсов?
так это утверждение для си - не справедливо?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 20:57

arthur2 писал(а):А ты думаешь, я логически это вывел? Не-а, просто так получается - чуть-чуть, но разница набегает. Причем, не всё время, а только иногда.

Давай живой пример, посмотрим.

arthur2 писал(а):Плохо. Зачем функции лишний параметр? что предлагаешь в неё передавать?

Он не лишний, а функциональный. Предлагаю передавать в него первое слагаемое. Снаружи вообще ничего не меняется. Как было sum(2, 77, 88), так и останется.

arthur2 писал(а):так это утверждение для си - не справедливо?

Справедлива, но не потому что Страуструп так сказал.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение arthur2 » 20.02.2011 (Вс) 21:18

Хакер писал(а):Предлагаю передавать в него первое слагаемое.
Не, ну это же был просто пример - реальная функция не такая.
Хакер писал(а):Давай живой пример, посмотрим.

Код: Выделить всё
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdarg.h>


      
void main()
{
   double s1,s2,d[5];
   int i;
   for(;;)
   {
      for(i=0; i<5; i++)d[i] = (double)rand()/rand();
      
      for(i=0,s1=0.0; i<5; i++)
         s1+=d[i];
      
      for (i=4,s2=0.0; i>=0; i--)
         s2+=d[i];
       
      if(s1==s2)printf("%f == %f\n",s1,s2);
      else printf("%f != %f\n",s1,s2);

      if (getch()==27)return;
   }
}
Последний раз редактировалось arthur2 20.02.2011 (Вс) 21:29, всего редактировалось 2 раз(а).
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 20.02.2011 (Вс) 21:20

arthur2 писал(а):Не, ну это же был просто пример - реальная функция не такая.

Какая разница? Ты до сих пор считаешь, что есть хоть какая-то минимальная разница?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение FireFenix » 21.02.2011 (Пн) 1:50

Вопрос немного не по теме...
Хакер, скажи, в чём ты раскрашивал/дополнял скрины?
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: функция с переменным числом параметров в Си, в чем косяк

Сообщение Хакер » 21.02.2011 (Пн) 9:18

FireFenix писал(а):Хакер, скажи, в чём ты раскрашивал/дополнял скрины?

viewtopic.php?p=6749787#p6749787
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в С/С++

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

    TopList