|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 10:48 am
|
Страница 1 от 1
|
[ 15 мнения ] |
|
Внимавайте със сметките, ако пишете на C/C++
| Автор |
Съобщение |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
 Внимавайте със сметките, ако пишете на C/C++
Става въпрос за случаите, когато имаме аритемтични действия с променливи, по-малки или равни на разредността на компютъра, като резултатът се присвоява на променлива с по-висока разрядност. Да разгледаме следният пример (имаме 8 битов процесор):
Нормално е в този случай да очакваме, че b ще има стойност 256, но на практика b приема стойност 0. Това е така, защото езикът C е контектстно-независим, т.е. не го интересува какво има от лявата страна. Тоест, горния израз е еквивалентен на: Компилатора просто зарежда a в 8 битов регистър, инкрементира го (при което, естествено, се получава препълване) и го премества в b. Аналогичен случай е и изразът от типа fload f = 1/3; при който f ще е 0.00, а не както очакваме 0.3(3). За това, трябва да се внимава и действията или да се извършват последователно: или да се каства навсякъде, където е нужно: И да накрая да отбележа, че ако имаме повече променливи от тип int8, които участват в израза, не е необходимо да се кастват всички, а само една от тях: Кастването на целия израз е нищожно, т.е. не води до желания резултат. Т.е. избягвайте изрази, подобни на този:
|
| Вто Май 31, 2005 9:46 am |
|
 |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 07, 2004 1:22 pm Мнения: 1949 Местоположение: София
|
Браво Реконструктор  За това последното все имам проблеми, все каствам целия израз щото се опасявам че компилатора няма да сложи в сметките a2 и a3 като 16-бита число....
|
| Вто Май 31, 2005 10:28 am |
|
 |
|
bateAz
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 4:11 pm Мнения: 3750 Местоположение: София
|
Добре е да се отбелязват такива най-често срещани грешки. Не че това не го пише във всеки буквар по Цъ, но често се забравя.
Да си кажа и аз. Преди време имаше проблеми с един промишлен пробор, който периодично (на около 1 сек) натрупва някаква величина, например дебит. Примерно - за тази секунда дебитът е бил 10куб. м. за секунда, значи изтеклата вода се е увеличила с 10. Това изглежда така
float total, debit, time;
(периодично)
total += debit * time;
Tова върви добре до време, след което "спира" да натрупва. Направо да ти потънат всички плуващи запетаи. Причина - добавяната величина е по-малка от най-младшия разряд на total. Понеже мутият компилер няма вградени 64-битови float, total се раздели на 2 променливи - младша и старша, по най-изкуствания начин.
Не е лошо подобни ограничения да се имат предвид в сметките.
|
| Вто Май 31, 2005 1:08 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Модерните компилатори на C/C++ ( Borland,MicroSoft, GNU ) имат опции, които третират този проблем като warning или дори може да се зададе да се генерира като error, когато се опиташ да правиш такива смесвания на типове. Най-добре е при такива преобразувания да се провери в документацията какво прави компилатора.
|
| Вто Май 31, 2005 1:20 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
c = (int)a +1
тва май решава проблема. Общо взето тия проблеми напрактика са незабелязани от глезени PC програмисти. Там на практика при чистите ПЦ приложения байтови данни не се ползват, всичко се маа на едро - int числа. На кой му пука, памет - колкото щеш. Ама на контролера - там паметта е кът, пестиш, пестиш и кво - стана некоя такава обърквация. И аз там съм затрил сумати време, накрая като видех листинга на асемблер и ми светна.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Вто Май 31, 2005 2:27 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Да, за това я пуснах темата, начинаещите да свикват с особеностите на националния лов.  Във фирмуера ми има доста такива места, но по стар навик всичко се извършва последователно, с цел прегледност ма кода - някои ПЦ навици са полезни. Вчера, обаче реших да понатоваря още малко процесора и написах един дългичък израз - доста време ми отне докато разбера ква е работата. 
|
| Вто Май 31, 2005 2:39 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Искаш да кажеш, че не поддържа дабъл (double) ??? Ебахти компилатора. 
|
| Вто Май 31, 2005 2:40 pm |
|
 |
|
ДедоБоре
Ранг: Форумен бог
Регистриран на: Нед Ное 21, 2004 11:31 pm Мнения: 10088
|
по принцип си прав
явното преобразуване на типове е проява на добър стил.
както и използване на void, където няма параметър.
твоя пример го пуснах на GCC
компилирано с -Wall и без оптимизации, резултата е
a=255, b=0
a=0, b=256
за avr-gcc резултата е същия - b е в 2 регистъра и се прави двубайтово сумиране (без оптимизация е много грозно) и резултата е същия
това, разбира се не обезмисля твоята бележка. на С това му е слилата, че можеш да правиш непозволени присвоявания, което понякога е и голям недостатък. особено като почнеш да хониш някой бъг, дето се случва един път в месеца.
ти какъв компилатор визираш?
|
| Вто Май 31, 2005 3:28 pm |
|
 |
|
amon_ra
Ранг: Минаващ
Регистриран на: Вто Дек 28, 2004 5:46 pm Мнения: 5
|
 А правилна ли е програмата?
Май използвате компилатори, които не поддържат ANSI стандарта. По принцип целия израз (дори и да съдържа само 8 битови променливи) трябва да се сметне като int.
Конкретно за програмата, тя наистина дава 0, но по друга причина. Спомнете си как се представят отрицателните числа. При 8bit тип данни със знак, 0xff е равно на -1, така че еквивалентната програма е:
Пробвах следната програма със avr-gcc (забележете, че ползвам цели числа без знак): И това е изхода:
Вижда се, че компилатора е сметнал b=0x100, след това е изместил надясно 8 бита и е получил 1, което записва в PORTA.
PS: току що видях, че и ДедоБоре го е тествал на avr-gcc 
|
| Вто Май 31, 2005 3:40 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Хех, не знаех за тази опция.  Значи полето за внимание се разширява - или внимаваш за опцията, или внимаваш с кастовете.  Но е добре, все пак, че е предвидено такова възможност.
|
| Вто Май 31, 2005 3:59 pm |
|
 |
|
Bezmozachen
Ранг: Популярен
Регистриран на: Сря Апр 27, 2005 2:47 pm Мнения: 349 Местоположение: Varna
|
Никога не съм писал на нещо различно от asembler за MCU-та и като ви гледам постингите съвсем загубих желание.
|
| Сря Юни 01, 2005 1:09 pm |
|
 |
|
bateAz
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 4:11 pm Мнения: 3750 Местоположение: София
|
Що, бе? C-то е много читава работа и ме кефи. Особено като скорост на писане и дебъгване. Но ЗАДЪЛЖИТЕЛНО си пускам и по един дизасемблерски листинг да го видя тъпия копилатор какви ги е надробил. Е, поне за някои неща 
|
| Сря Юни 01, 2005 1:22 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Браво на колегата amon_ra, не се сетих да погледна че числата са със знак, иначе и аз се зачудих защо аджиба компилатора ще свива резултата до 8 бита вместо да го разширява до 16-битов резултат.
|
| Сря Юни 01, 2005 2:19 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Не е тва причината - махни знака и пак ше е същото.
|
| Сря Юни 01, 2005 2:21 pm |
|
 |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 07, 2004 1:22 pm Мнения: 1949 Местоположение: София
|
Ако някой ме накара да напиша
това на асемблер, предполагам ще ми отнеме около 20 мин... Със Ц го пишеш за 1 минутка и кашата в процесора си е същата както и на асемблер...
|
| Сря Юни 01, 2005 5:30 pm |
|
|
|
Страница 1 от 1
|
[ 15 мнения ] |
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 4 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|