问题
So, if I understood it well, integral promotion provides that: char, wchar_t, bool, enum, short
types ALWAYS are converted to int
(or unsigned int
). Then, if there are different types in an expression, further conversion will be applied.
Am I understanding this well?
And if yes, then my question: Why is it good? Why? Don't become char/wchar_t/bool/enum/short
unnecessary? I mean for example:
char c1;
char c2;
c1 = c2;
As I described before, char
ALWAYS is converted to int
, so in this case after automatic converting this looks like this:
int c1;
int c2;
c1 = c2;
But I can't understand why is this good, if I know that char
type will be enough for my needs.
回答1:
The conversions you're asking about are the usual arithmetic conversions and the integer promotions, defined in section 6.3.1.8 of the latest ISO C standard. They're applied to the operands of most binary operators ("binary" meaning that they take two operands, such as +
, *
, etc.). (The rules are similar for C++. In this answer, I'll just refer to the C standard.)
Briefly the usual arithmetic conversions are:
- If either operand is
long double
, the other operand is converted tolong double
. - Otherwise, if either operand is
double
, the other operand is converted todouble
. - Otherwise, if either operand is
float
, the other operand is converted tofloat
. - Otherwise, the integer promotions are performed on both operands, and then some other rules are applied to bring the two operands to a common type.
The integer promotions are defined in section 6.3.1.1 of the C standard. For a type narrower than int
, if the type int
can hold all the values of the type, then an expression of that type is converted to int
; otherwise it's converted to unsigned int
. (Note that this means that an expression of type unsigned short
may be converted either to int
or to unsigned int
, depending on the relative ranges of the types.)
The integer promotions are also applied to function arguments when the declaration doesn't specify the type of the parameter. For example:
short s = 2;
printf("%d\n", s);
promotes the short
value to int
. This promotion does not occur for non-variadic functions.
The quick answer for why this is done is that the standard says so.
The underlying reason for all this complexity is to allow for the restricted set of arithmetic operations available on most CPUs. With this set of rules, all arithmetic operators (other than the shift operators, which are a special case) are only required to work on operands of the same type. There is no short + long
addition operator; instead, the short
operand is implicitly converted to long
. And there are no arithmetic operators for types narrower than int
; if you add two short
values, both arguments are promoted to int
, yielding an int
result (which might then be converted back to short
).
Some CPUs can perform arithmetic on narrow operands, but not all can do so. Without this uniform set of rules, either compilers would have to emulate narrow arithmetic on CPUs that don't support it directly, or the behavior of arithmetic expressions would vary depending on what operations the target CPU supports. The current rules are a good compromise between consistency across platforms and making good use of CPU operations.
回答2:
Storage types are never automatically converted. You only get automatic integer promotion as soon as you start doing integer arithmetics (+
, -
, bitshifts, ...) on those variables.
char c1, c2; // stores them as char
char c3 = c1 + c2; // equivalent to
char c3 = (char)((int)c1 + (int)c2);
回答3:
if I understood it well, integral promotion provides that: char, wchar_t, bool, enum, short types ALWAYS converted to int (or unsigned int).
Your understanding is only partially correct: short types are indeed promoted to int
, but only when you use them in expressions. The conversion is done immediately before the use. It is also "undone" when the result is stored back.
The way the values are stored remains consistent with the properties of the type, letting you control the way you use your memory for the variables that you store. For example,
struct Test {
char c1;
char c2;
};
will be four times as small as
struct Test {
int c1;
int c2;
};
on systems with 32-bit int
s.
回答4:
The conversion is not performed when you store the value in the variable. The conversion is done if you cast the value or if you perform some operation like some arithmetic operation on it explicitly
回答5:
It really depends on your underlying microprocessor architecture. For example, if your processor is 32-bit, that is its native integer size. Using its native integer size in integer computations is better optimized.
回答6:
Type conversion takes place when arithmetic operations, shift operations, unary operations are performed. See what standard says about it:
C11; 6.3.1.4 Real floating and integer:
If an
int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anin
t; otherwise, it is converted to anunsigned int
. These are called the integer promotions.58) All other types are unchanged by the integer promotions.58.The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary
+
,-
, and~
operators, and to both operands of the shift operators,1 as specified by their respective subclauses
1. Emphasis is mine.
来源:https://stackoverflow.com/questions/20747614/why-does-c-c-automatically-convert-char-wchar-t-short-bool-enum-types-to-int