Цитата(_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) и не надеяться на то, что на данной платформе конкретный компилятор сделает это за программиста, причем, вполне определенным образом.