问题
I looked around and only found more complicated posts involving pointers. I'm learning C, and just wanted to confirm my understanding of a few examples. (These examples assume int and short int sizes of 32 and 16 bits, respectively.)
Initial code:
int int1 = 70000;
int int2;
short int shortInt1 = -70;
short int shortInt2, shortInt3;
And some sample conversions:
shortInt2 = int1 / shortInt1;
My understanding:
i. Division is conducted (70000 / -70), yielding a value of -1000
ii. Because int has higher precedence than short int, the result is assigned to an anonymous signed int
iii. Anonymous signed int is cast to an anonymous signed short int
iv. The value of the anonymous signed short int is assigned to shortInt2
v. The anonymous signed int and anonymous signed short int are garbage collected
vi. Result: -1000
shortInt3 = (short) int1 / shortInt1;
My understanding:
i. Because casting has precedence over arithmetic, int1 is cast to an anonymous signed short int. Overflow occurs, giving it a value of 4464
ii. The division is conducted, and the result of -63 is assigned to a second anonymous signed short int
iii. The value of the second anonymous signed short int is assigned to shortInt3
iv. Both anonymous signed short ints are garbage collected
v. Result: -63
int2 = (short)(int1 / shortInt2);
This is the example by which I'm most confused. I understand that casting has precedence over arithmetic, but here it seems the parentheses around the arithmetic are giving the arithmetic precedence over the casting. (Which I suppose makes sense, since the casting operation needs some value to cast.)
So, my understanding:
i. Division is carried out and, as int has higher precedence, the value of the division is assigned to an anonymous signed int.
ii. The anonymous signed int is cast to an anonymous signed short int
iii. Arithmetic right shift is performed on the anonymous signed short int, expanding it into another anonymous signed int
iv. The value of the second anonymous signed int is assigned to int2
v. The anonymous signed int (the first), anonymous signed short int, and anonymous signed int (the second) are garbage collected
vi. Value: -1000
回答1:
Your question makes a number of incorrect assumptions and uses incorrect terminology. I'll start by explainin what the C standard says about your sample code.
You can grab a copy of the latest draft of the C standard, N1570. The "usual arithmetic conversions" are described in section 6.3.1.8; the integer promotions are describe in 6.3.1.1.
int int1 = 70000;
Given your assumptions, int
is 32 bits, so it's big enough to hold the value 70000
. (There are systems where int
is only 16 bits; on such systems, this would give an implementation-defined result.)
int int2;
short int shortInt1 = -70;
70
is a constant of type int
. The unary -
operator is applied to the resulting value, yielding an int
value of -70. The initialization causes that int
value to be converted to the type of the target object. Conversions preserve values whenever possible, and since short
is guaranteed to be at least 16 bits wide, shortInt1
is set to the obvious value.
short int shortInt2, shortInt3;
shortInt2 = int1 / shortInt1;
The division operator applies the usual arithmetic conversions to its two operands. This is a moderately complicated set of rules, designed to guarantee that both operands are of the same type (for the most part, C doesn't have mixed-type arithmetic operators). This case is fairly simple: the short int
operand is converted to int
, and the /
is then applied to two int
operands and yields an int
result. The value is -1000
.
The assignment then causes that result to be converted from int
to short
. Again, short
is big enough to hold that value, so shortInt2
gets the value -1000
(of type short
, not int
).
Most expressions in C are evaluated without regard to the context in which they appear. A division on the right hand side of an assignment is not affected by the type of the left hand side. It's evaluated in isolation and then converted to the target type if necessary.
shortInt3 = (short) int1 / shortInt1;
The cast converts the value of int1
to type short
, so the /
operator has two operands of type short
. But the usual arithmetic conversions on integer operands include the integer promotions, which convert both short
operands to type int
. The int
-by-int
division yields an int
result, which is then converted to short
and assigned to shortInt3
.
int2 = (short)(int1 / shortInt2);
The division int1 / shortInt2
applies the usual arithmetic conversions, which convert the right operand from short
to int
. The result of the int
-by-int
conversion is then converted to short
by the cast. The short
result is then converted to int
because it's being assigned to an int
target object.
Now to clear up a few things you wrote:
Because int has higher precedence than short int, the result is assigned to an anonymous signed int
Types don't have precedence. Operators do. (Types have rank, which is used to determine the *usual arithmetic conversions".)
You seem to be assuming that the result of evaluating an expression must be assigned to some object (variable). That's not the case. Evaluating an expression yields a result. That result is a particular value, and is of some particular type, but it needn't be stored anywhere. (Perhaps it will be stored temporarily in a register, or even in some memory location, but that's an implementation detail that we can safely ignore.) There's no need to invent an "anonymous" anything to hold the result of an expression. The result simply is. Eventually it might be stored in an object, or passed to a function, or used as the operand of another operator. The way that's done is not defined by the C standard.
来源:https://stackoverflow.com/questions/25961247/integer-conversion-explicit-and-implicit-casting