Integer conversion (explicit and implicit casting)

℡╲_俬逩灬. 提交于 2019-12-12 19:17:21

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!