| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Data types convertions http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=4001 |
Страница 1 от 2 |
| Автор: | HCL [ Чет Апр 05, 2007 2:34 pm ] | |||||||||||||||||||||||||||
| Заглавие: | Data types convertions | |||||||||||||||||||||||||||
Скоро се отвори в една тема вьпросът. При мен се получава следното омазване. В документацията на компилатора C166 пише
Какво се получава в действителност. Следният код на C.
frequency_real е голбална променлива от тип unsigned long. Всичко е нормално, компилаторьт разбира, че резултатьт от умножението ще инициализира 32bit-oва променлива и използва MD регистьр-а. Какво става обаче ако малко модифицирам кода, като "забравя" да конвертирам рьчно. Все пак се предполага, чe компилаторьт трябва да сьобрази последното. На последния обаче не му идва на ум, че резултатьт implies another data type и ще се наложи да се сьхрани в 32bit-ова променлива и прави слената глупост.
Спестява ми много интелигентно мултиплицирането и записва в cтаршите 16bit-а 0x0000, келеш |
||||||||||||||||||||||||||||
| Автор: | setoy [ Чет Апр 05, 2007 2:50 pm ] |
| Заглавие: | |
Keil-а редовно прави такива простотии. Понякокага дори се налага да си правиш междинни променливи с явно преобразуване на тип.... иначе маркуча. |
|
| Автор: | Nikola Kirov [ Чет Апр 05, 2007 5:53 pm ] |
| Заглавие: | |
не вдявам от този асемблер и не ми се гадае но от гледна точка на C frequency_real = (unsigned long)ad * 7; трябва да стане следното - ad се преобразува до unsigned long след което резултата от това преобразуване се умножава по 7 тоест имаме unsigned long * unsigned long като резултата от тази операция е unsigned long. След това се каства до unsigned int и това се присвоява на frequency_real. Ако компилатора е направил друго значе е бъг. |
|
| Автор: | HCL [ Чет Апр 05, 2007 6:08 pm ] | |||||||||
| Заглавие: | ||||||||||
frequency_real е от тип unsigned long. А компилаторьт в този пример, горния, реагира доста интелигентно, като мултиплицира два 16bit-ови регистьра и сьхранява 32bit-овия резултат в MD регистьра, и това с една инструкция MULU, бива си го контролерчето. Проблемьт е в долния код, там кьдето липсва (unsigned long). В този случай умножава стойността в 16bit-овия регистьр с 7, като шифтва 3 пьти в ляво и изважда ведньж стойността на регистьра от резултата, и това всичко го записва в ниските 2 байта на 32bit-овата глобална frequency_real, а старшите 2 байта нулира. Тоест резултата е 16bit-ов, за мен това е бьг. И обeца на ухото, навсякьде да слагам едно рьчно конвертиране от рода на (unsigned long) кьдето боравя с променливи от различен вид. |
||||||||||
| Автор: | miro_atc [ Чет Апр 05, 2007 6:16 pm ] | |||||||||
| Заглавие: | ||||||||||
Да не се изложа ама мисля че ВСЕКИ компилатор ще постъпи по тоя начин. Имаш:
Преобразуването по тип се прави по повод конкретна операция, а ти имаш ДВЕ операции, едната умножение - другата присвояване. По задължение първо се извършва умножение, което е между два uint, значи и операцията ще е такава. Втората операция е присвояване, тогава това което е отдявсно се каства до каквото пише вляво... |
||||||||||
| Автор: | HCL [ Чет Апр 05, 2007 6:24 pm ] |
| Заглавие: | |
Така като го обясняваш звучи доста логично. Опитах с 7L вместо 7 и работата заспа. А аз оплюх компилтатора, тя била в мен грешката |
|
| Автор: | Реконструктор [ Чет Апр 05, 2007 10:30 pm ] | ||||||||||||||||||
| Заглавие: | |||||||||||||||||||
Константите, мисля, по стандарт бяха int. Тая седмица е int със знак. Стойността на целия израз, доколкото помня, беше с типа на първия операнд. |
|||||||||||||||||||
| Автор: | Nikola Kirov [ Чет Апр 05, 2007 10:58 pm ] |
| Заглавие: | |
Да по стандарт типа на резултата е типа на първия операнд със сигурност. И това че типа на константите е int също е по стандарта май. Но на практика съм забелязал че не се спазва,от IAR за AVR поне съм сигурен. Използва се тип при който кода е най ефективен. В случая мисля че най ефективно би било да е unsigned int но всъщност може и да греша. Но като цяло не би трябвало в случая типа на константата да влияе на резултата. Евентуално на оптималноста на кода само. |
|
| Автор: | ДедоБоре [ Пет Апр 06, 2007 8:47 am ] |
| Заглавие: | |
и затова се ползва винаги явно преобразуване на типовете. за да се елиминира влиянието на диалекта и преводача ПС: стандартите са приемат, за да не се спазват |
|
| Автор: | miro_atc [ Пет Апр 06, 2007 10:13 am ] | |||||||||
| Заглавие: | ||||||||||
Не съм съгласен... Типът на резултата се определя от типовете на операндите без значение, кой е първи и кой е втори. Умножение на int с int дава int, умножение на uint с int дава int, умножение на int с лонг дава лонг.... Поне така е в математиката, а който не вярва за програмирането може да провери че a*b == b*a //независимо от типовете на а и b Иначе това което казваш се отнася до това кой операнд се извлича първи - левия или десния, ама това е една друга приказка... |
||||||||||
| Автор: | Nikola Kirov [ Пет Апр 06, 2007 11:15 am ] |
| Заглавие: | |
но при програмирането е намесена и размерноста на типовете x = a*b от математиката при програмирането е x = (а*b) & 0xFF да кажем за случай на променливи от тип unsigned char. |
|
| Автор: | setoy [ Пет Апр 06, 2007 12:04 pm ] |
| Заглавие: | |
Принципно кеила не се справя с преобразуването на типове както трябва. Изрази от сорта на if (float<int) или дори if (float <0) го затрудняват сериозно. float винаги се оказва по-малко (или по-голямо, не помня какво) float temp; temp=(float) int; if (float <temp) Ако искаш кода ти да работи винаги де... Изрази от сорта на a=-b; също са ми създавали проблеми. Уоркароунд: а=0; а-=b; Олигофрении колкото искаш. |
|
| Автор: | miro_atc [ Пет Апр 06, 2007 1:12 pm ] | ||||||||||||||||||
| Заглавие: | |||||||||||||||||||
то и в математиката е същото бе Никола, ако си дефинираш че работиш в подмножество X (0<=х<=255) от множеството на целочислените числа, си оставаш в това подмножество... Така че, твърдението:
е вярно само за операции с един операнд и някои операции при които позицията на операндите има значение. За прости симетрични операции като събиране/умножение - не е вярно Обратното би означавало A*B да е различно от B*A, когато А и В са от различни типове... Примерно ако: unsigned char a=5; unsigned int b=100; unsigned int ab, ba; ab = a*b; ba = b*a; Според теб излиза че ab=244 , ba =500 - което очевидно не е така |
|||||||||||||||||||
| Автор: | Nikola Kirov [ Вто Апр 10, 2007 11:02 am ] |
| Заглавие: | |
Да прав си. Но в такъв случай трябва да има някакво правило. Какъв ще е резултата например от (unsigned int * signed int) операция |
|
| Автор: | Реконструктор [ Вто Апр 10, 2007 11:20 am ] | |||||||||
| Заглавие: | ||||||||||
Каства се към типа на променливата, на която се присвоява. Например, -1 * 1 = 4294967295 (0xFFFFFFFF) |
||||||||||
| Страница 1 от 2 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|