| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Внимавайте със сметките, ако пишете на C/C++ http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=700 |
Страница 1 от 1 |
| Автор: | Реконструктор [ Вто Май 31, 2005 9:46 am ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Заглавие: | Внимавайте със сметките, ако пишете на C/C++ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Става въпрос за случаите, когато имаме аритемтични действия с променливи, по-малки или равни на разредността на компютъра, като резултатът се присвоява на променлива с по-висока разрядност. Да разгледаме следният пример (имаме 8 битов процесор):
Нормално е в този случай да очакваме, че b ще има стойност 256, но на практика b приема стойност 0. Това е така, защото езикът C е контектстно-независим, т.е. не го интересува какво има от лявата страна. Тоест, горния израз е еквивалентен на:
Компилатора просто зарежда a в 8 битов регистър, инкрементира го (при което, естествено, се получава препълване) и го премества в b. Аналогичен случай е и изразът от типа fload f = 1/3; при който f ще е 0.00, а не както очакваме 0.3(3). За това, трябва да се внимава и действията или да се извършват последователно:
или да се каства навсякъде, където е нужно:
И да накрая да отбележа, че ако имаме повече променливи от тип int8, които участват в израза, не е необходимо да се кастват всички, а само една от тях:
Кастването на целия израз е нищожно, т.е. не води до желания резултат. Т.е. избягвайте изрази, подобни на този:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Автор: | Predator_MF [ Вто Май 31, 2005 10:28 am ] |
| Заглавие: | |
Браво Реконструктор |
|
| Автор: | bateAz [ Вто Май 31, 2005 1:08 pm ] |
| Заглавие: | |
Добре е да се отбелязват такива най-често срещани грешки. Не че това не го пише във всеки буквар по Цъ, но често се забравя. Да си кажа и аз. Преди време имаше проблеми с един промишлен пробор, който периодично (на около 1 сек) натрупва някаква величина, например дебит. Примерно - за тази секунда дебитът е бил 10куб. м. за секунда, значи изтеклата вода се е увеличила с 10. Това изглежда така float total, debit, time; (периодично) total += debit * time; Tова върви добре до време, след което "спира" да натрупва. Направо да ти потънат всички плуващи запетаи. Причина - добавяната величина е по-малка от най-младшия разряд на total. Понеже мутият компилер няма вградени 64-битови float, total се раздели на 2 променливи - младша и старша, по най-изкуствания начин. Не е лошо подобни ограничения да се имат предвид в сметките. |
|
| Автор: | ¶ [ Вто Май 31, 2005 1:20 pm ] |
| Заглавие: | |
Модерните компилатори на C/C++ ( Borland,MicroSoft, GNU ) имат опции, които третират този проблем като warning или дори може да се зададе да се генерира като error, когато се опиташ да правиш такива смесвания на типове. Най-добре е при такива преобразувания да се провери в документацията какво прави компилатора. |
|
| Автор: | Цецо [ Вто Май 31, 2005 2:27 pm ] |
| Заглавие: | |
c = (int)a +1 тва май решава проблема. Общо взето тия проблеми напрактика са незабелязани от глезени PC програмисти. Там на практика при чистите ПЦ приложения байтови данни не се ползват, всичко се маа на едро - int числа. На кой му пука, памет - колкото щеш. Ама на контролера - там паметта е кът, пестиш, пестиш и кво - стана некоя такава обърквация. И аз там съм затрил сумати време, накрая като видех листинга на асемблер и ми светна. |
|
| Автор: | Реконструктор [ Вто Май 31, 2005 2:39 pm ] | |||||||||
| Заглавие: | ||||||||||
Да, за това я пуснах темата, начинаещите да свикват с особеностите на националния лов. |
||||||||||
| Автор: | Реконструктор [ Вто Май 31, 2005 2:40 pm ] | |||||||||
| Заглавие: | ||||||||||
Искаш да кажеш, че не поддържа дабъл (double) ??? Ебахти компилатора. |
||||||||||
| Автор: | ДедоБоре [ Вто Май 31, 2005 3:28 pm ] | |||||||||
| Заглавие: | ||||||||||
по принцип си прав явното преобразуване на типове е проява на добър стил. както и използване на void, където няма параметър. твоя пример го пуснах на GCC
компилирано с -Wall и без оптимизации, резултата е a=255, b=0 a=0, b=256 за avr-gcc резултата е същия - b е в 2 регистъра и се прави двубайтово сумиране (без оптимизация е много грозно) и резултата е същия това, разбира се не обезмисля твоята бележка. на С това му е слилата, че можеш да правиш непозволени присвоявания, което понякога е и голям недостатък. особено като почнеш да хониш някой бъг, дето се случва един път в месеца. ти какъв компилатор визираш? |
||||||||||
| Автор: | amon_ra [ Вто Май 31, 2005 3:40 pm ] | |||||||||||||||||||||||||||
| Заглавие: | А правилна ли е програмата? | |||||||||||||||||||||||||||
Май използвате компилатори, които не поддържат ANSI стандарта. По принцип целия израз (дори и да съдържа само 8 битови променливи) трябва да се сметне като int. Конкретно за програмата, тя наистина дава 0, но по друга причина. Спомнете си как се представят отрицателните числа. При 8bit тип данни със знак, 0xff е равно на -1, така че еквивалентната програма е:
Пробвах следната програма със avr-gcc (забележете, че ползвам цели числа без знак):
И това е изхода:
Вижда се, че компилатора е сметнал b=0x100, след това е изместил надясно 8 бита и е получил 1, което записва в PORTA. PS: току що видях, че и ДедоБоре го е тествал на avr-gcc |
||||||||||||||||||||||||||||
| Автор: | Реконструктор [ Вто Май 31, 2005 3:59 pm ] |
| Заглавие: | |
Хех, не знаех за тази опция. |
|
| Автор: | Bezmozachen [ Сря Юни 01, 2005 1:09 pm ] |
| Заглавие: | |
Никога не съм писал на нещо различно от asembler за MCU-та и като ви гледам постингите съвсем загубих желание. |
|
| Автор: | bateAz [ Сря Юни 01, 2005 1:22 pm ] | |||||||||
| Заглавие: | ||||||||||
Що, бе? C-то е много читава работа и ме кефи. Особено като скорост на писане и дебъгване. Но ЗАДЪЛЖИТЕЛНО си пускам и по един дизасемблерски листинг да го видя тъпия копилатор какви ги е надробил. Е, поне за някои неща |
||||||||||
| Автор: | ¶ [ Сря Юни 01, 2005 2:19 pm ] |
| Заглавие: | |
Браво на колегата amon_ra, не се сетих да погледна че числата са със знак, иначе и аз се зачудих защо аджиба компилатора ще свива резултата до 8 бита вместо да го разширява до 16-битов резултат. |
|
| Автор: | Реконструктор [ Сря Юни 01, 2005 2:21 pm ] | |||||||||
| Заглавие: | ||||||||||
Не е тва причината - махни знака и пак ше е същото. |
||||||||||
| Автор: | Predator_MF [ Сря Юни 01, 2005 5:30 pm ] | ||||||||||||||||||
| Заглавие: | |||||||||||||||||||
Ако някой ме накара да напиша
това на асемблер, предполагам ще ми отнеме около 20 мин... Със Ц го пишеш за 1 минутка и кашата в процесора си е същата както и на асемблер... |
|||||||||||||||||||
| Страница 1 от 1 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|