реклама на сайте
подробности

 
 
> Type conversions в CodeVision, unsigned char->float
Gogan
сообщение Dec 28 2007, 13:21
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 83
Регистрация: 25-10-07
Из: Киев
Пользователь №: 31 728



Есть вот такой проргамный код для АВР(например):

unsigned char a = 100;
float b = 20;

далее в программе

if( b < -a ){...}

так вот оказывается, в таком случаее условие выполняется.
Если кастовать вот так :

if( b < - (int) a ) {...}

тогда все ок. Объясните почему? Я не могу понять, что с чем сравнивается, если не кастовать, и почему так происходит?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
ReAl
сообщение Dec 28 2007, 20:57
Сообщение #2


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Gogan @ Dec 28 2007, 15:21) *
unsigned char a = 100;
float b = 20;

далее в программе

if( b < -a ){...}

так вот оказывается, в таком случаее условие выполняется.
Если кастовать вот так :

if( b < - (int) a ) {...}

тогда все ок. Объясните почему? Я не могу понять, что с чем сравнивается, если не кастовать, и почему так происходит?

На мой взгляд, компилятор не прав. Согласно стандарту С он должен оба эти if-а обрабаотывать одинаково и так, как второй. Есть такая штука, как integer promotion rules (integer promotions), согласно им любой целочисленный тип, который меньше int-а, должен приводиться к int перед вычислением выражений. Даже для
Код
char a,b,c;
a = b + c;
- привести к int, сложить, результат усечь и присвоить a.
Это требования к "абстрактной машине", дальше можно дать свободу и не делать приведение к int, но только в случае, если от такого неделания результат не изменится.
В данном случае -a это уже подвыражение с унарным минусом, перед его вычислением компилятору надо было привести a к int (что во втором примере сделано вручную), потом применить минус, потом, согласно правилам автоматических преобразований типов, результат привести к float и сравнить.
Так что тут компилятор не имел права делать -a в пределах байта.

Цитата(Gogan @ Dec 28 2007, 20:33) *
eeprom unsigned char edata[20][8]={{90,0,...},{}...};
unsigned int a;

далее в тексте
a=edata[0][0]+edata[0][1]<<8;

т.е. интегер хранится в двух первых байтах, сначала младший потом старший. Компилер выдал, что edata[0][1]<<8 получится в любом случае 0. Я переписал
a=(int)edata[0][0]+edata[0][1]<<8;

опять неправильно. Компилер не ругался, но результат был 90х256=23040. Правильным вариантом оказалось:
a=edata[0][0]+(int)edata[0][1]<<8;

Выбрось каку!!!
Правильный компилятор (соответствующий стандарту) во всех трёх приведённых тобой вариантах должен был дать одинаковый результат, впрочем, не тот, который ты ожидаешь smile.gif
Приведение к int делать вообще не нужно, оно должно было быть сделано согласно integer promotions самим компилятором.
А вот дальше - у оператора сложения приоритет выше, чем у операции сдвига (с моей точки зрения, приоритет сдвигов должен бы быть между приоритетами *% и +-, но K&R когда-то решили иначе и стандарт есть стандарт), поэтому
a + b << 8;
должно вычисляться всегда как
( a + b ) << 8;

А то, что хотелось сделать, следует записывать как
a + ( b << 8 );


p.s. Не понимаю, как можно пользоваться компилятором, настолько не соответствующим стандарту...
Или он позиционируется как "компилятор С-подобного языка программирования" ???


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 29 2007, 08:38
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(ReAl @ Dec 28 2007, 23:57) *
Приведение к int делать вообще не нужно, оно должно было быть сделано согласно integer promotions самим компилятором.

ISO9899 п.6.3.1.1 абз.2
Цитата
The following may be used in an expression wherever an int or unsigned int may be used:
— An object or expression with an integer type whose integer conversion rank is less than the rank of int and unsigned int.
— A bit-field of type _Bool, int, signed int, or unsigned int.
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.
Так, должно или может быть сделано?
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Gogan   Type conversions в CodeVision   Dec 28 2007, 13:21
- - Kuzmi4   2 Gogan - последний вариант - как бы правильней - ...   Dec 28 2007, 13:25
- - sergik_vrn   Цитата(Gogan @ Dec 28 2007, 16:21) Есть в...   Dec 28 2007, 14:33
|- - defunct   Цитата(sergik_vrn @ Dec 28 2007, 17:33) т...   Dec 28 2007, 15:15
|- - sergik_vrn   Цитата(defunct @ Dec 28 2007, 18:15) Логи...   Dec 29 2007, 06:54
- - Gogan   Огромное спасибо за ответы! Теперь уяснил. Сег...   Dec 28 2007, 18:33
|- - Gogan   Цитата(ReAl @ Dec 28 2007, 22:57) А то, ч...   Dec 29 2007, 06:25
|- - ReAl   Цитата(Палыч @ Dec 29 2007, 10:38) ISO989...   Dec 29 2007, 09:15
- - WHALE   Выбрось каку!!! Обьясните тупому,плиз...   Dec 29 2007, 06:25
- - Qwertty   Имхо правильный вариант: eeprom unsigned int edata...   Dec 29 2007, 06:47
- - WHALE   Дык я про это и пишу.В вашем примере это несомненн...   Dec 29 2007, 07:15
|- - sergik_vrn   Цитата(WHALE @ Dec 29 2007, 10:15) [..] а...   Dec 29 2007, 08:21
- - WHALE   То есть если у меня сложная составная операция с д...   Dec 29 2007, 08:29
- - sergik_vrn   Цитата(WHALE @ Dec 29 2007, 11:29) То ест...   Dec 29 2007, 08:39


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 12:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.0141 секунд с 7
ELECTRONIX ©2004-2016