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

 
 
> Проблемы c IAR AVR!
Yura_Kyiv
сообщение Nov 21 2006, 11:31
Сообщение #1





Группа: Новичок
Сообщений: 3
Регистрация: 7-11-06
Пользователь №: 22 049



Имеется IAR 4.20. Выполняю небольшую программу и угадайте, что я получаю на выходе??? 32640+4294934528!!

unsigned long int L1=0,L2=0;
unsigned char C1;

int main( void )
{
C1=0x80;
L1=C1*255;
L2=C1*256;
return (L1+L2);
}

В Borland C++, Visual Studio результат правильный!
Только не надо говорить, что надо писать так или C1 должно быть Long Int!
L2=(long int)C1*256;

Как правильно настроить IAR????
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
arttab
сообщение Nov 21 2006, 12:43
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371



Придется правильно писать, поскольку сначало делаются вычисления, а потом приведение к типу


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
tag
сообщение Nov 22 2006, 09:39
Сообщение #3


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

Группа: Свой
Сообщений: 151
Регистрация: 21-02-06
Пользователь №: 14 561



Цитата(arttab @ Nov 21 2006, 13:43) *
Придется правильно писать, поскольку сначало делаются вычисления, а потом приведение к типу

...вообще-то можно типами оперировать и во время вычислений

Цитата(Yura_Kyiv @ Nov 21 2006, 12:31) *
Имеется IAR 4.20. Выполняю небольшую программу и угадайте, что я получаю на выходе??? 32640+4294934528!!

unsigned long int L1=0,L2=0;
unsigned char C1;

int main( void )
{
C1=0x80;
L1=C1*255;
L2=C1*256;
return (L1+L2);
}

В Borland C++, Visual Studio результат правильный!
Только не надо говорить, что надо писать так или C1 должно быть Long Int!
L2=(long int)C1*256;

Как правильно настроить IAR????




...странновато, потому что в процессе вычисления выражения компилятор сам должен приводить типы, в данном случае к unsigned long int, может компилятор кривой? ...попробуй в опциях для компилятора указать Strict ISO/ANSI
Go to the top of the page
 
+Quote Post
_Bill
сообщение Nov 22 2006, 10:18
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(tag @ Nov 22 2006, 09:39) *
...странновато, потому что в процессе вычисления выражения компилятор сам должен приводить типы, в данном случае к unsigned long int, может компилятор кривой? ...попробуй в опциях для компилятора указать Strict ISO/ANSI

Компилятор тут ни при чем. Он правильно все делает, он приводит к старшему типу, в соответствии с типом одного из операндов. А вот результат операции перед присваиванием приводится к типу данных в левой части выражения. Но если результат операции уже неправильный (при переполнении), то это приведение ничего не изменит.
Go to the top of the page
 
+Quote Post
osnwt
сообщение Nov 22 2006, 12:34
Сообщение #5


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

Группа: Свой
Сообщений: 175
Регистрация: 26-01-06
Из: Sevastopol
Пользователь №: 13 664



Цитата(_Bill @ Nov 22 2006, 09:18) *
Компилятор тут ни при чем. Он правильно все делает, он приводит к старшему типу, в соответствии с типом одного из операндов.

Хотел тоже написать нечто вроде этого. Однако, имея привычку писать то, в чем уверен (или писать с оговоркой), копнул стандарт языка. И вот что там обнаружил (см. выделенное мною):

Цитата
Type Conversions

Within several contexts the translator converts the type of a scalar expression (or subexpression). The conversions are called:

* promoting
* balancing
* assigning
* type casting

This section describes each of these conversions and the context in which it occurs. It also shows how the translator determines the value of the converted type from the value of the original type.

Promoting

Except when it is the operand of the sizeof operator, an integer rvalue expression has one of four types:

* int
* unsigned int
* long
* unsigned long

When you write an expression in an rvalue subcontext and the expression has an integer type that is not one of these types, the translator promotes its type. If all of the values representable in the original type are also representable as type int, then the promoted type is int. Otherwise, the promoted type is unsigned int.

Thus, for signed char, short, and any signed bitfield type, the promoted type is int. For each of the remaining integer types (char, unsigned char, unsigned short, any plain bitfield type, or any unsigned bitfield type), the effect of these rules is to favor promoting to int wherever possible, but to promote to unsigned int if necessary to preserve the original value in all possible cases.

For example:

signed char ch;
unsigned short us, f(char *, ...);
f("%i%x", ch, // ch becomes int
us); // us becomes int or unsigned int

Balancing

When you write an infix operator that has two arithmetic rvalue operands, the translator frequently determines the type of the result by balancing the types of the two operands. To balance two types, the translator applies the following rules to the promoted types of the operands:

* Unless the two types are unsigned int and long, the balanced type is the promoted type (of the two) that occurs later in the sequence: int, unsigned int, long, unsigned long, float, double, and long double.
* If the two types are unsigned int and long and the type long can represent all values of type unsigned int, the balanced type is long.
* Otherwise, the balanced type is unsigned long.

Each of the operands is converted to the balanced type, the arithmetic operation occurs between the now identical types, and the result of the operation has the balanced type. For example:

int i;
long lo;
double d;
return ((i + lo) // i becomes long
+ d); // (i + lo) becomes double


Иначе говоря, согласно вышесказанному, если имеется выражение с разными целочисленными типами справа, то каждый из операндов должен быть преобразован к одному из названных типов - в данном случае это int или unsigned int.

С этой точки зрения нельзя не согласиться с Yura_Kyiv, что имеет место отклонение от стандарта.

С другой стороны, такая трактовка на 8-битных системах существенным образом снизит эффективность вычислений. Изменить это можно явным приведением типа вроде (int)C1 или т.п. А вот при обратном поведении компилятора это было бы неподконтрольно.

И с этой точки зрения разработчики IAR дают возможность явно указать свои намерения программисту.

Не стану утверждать, что они неправы. Я не уверен, что они не придерживаются какого-нибудь более нового стандарта C или Embedded C, где это оговорено. Но со своей стороны скажу, что лично я никогда не рассчитываю на подобные автоматические конверсии типов. Если есть основания допускать, что результат выражения с операндами типа char выйдет за рамки char - лучше самому явно привести типы к максимально возможному (Balancing) и не надеяться на то, что на данной платформе конкретный компилятор сделает это за программиста, причем, вполне определенным образом.
Go to the top of the page
 
+Quote Post



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

 


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


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