char类型内存存储和加减问题

今天处理一些char类型存储的一些问题,附上所分析的源代码

 1 #include<stdio.h>
 2 
 3 int main(int argc,char *argv[])
 4 {
 5 
 6     char cA;
 7     unsigned char ucB;
 8     unsigned short usC;
 9     cA = 128;
10     ucB = 128;
11 
12     usC = cA+ucB;
13     printf("0x%x\n",usC);
14 
15     usC=cA+(short)ucB;
16     printf("0x%x\n",usC);
17 
18     usC = (unsigned char)cA+ucB;
19     printf("0x%x\n",usC);
20 
21     usC=cA+(char)ucB;
22     printf("0x%x\n",usC);
23 
24 
25     return 0;
26 
27 }

(unsigned short)(cA+(char)ucB) = 65280  0xFF00,求解答!!

 

下面是unix论坛高手给的解答,很专业,谢谢Alister!!

Short version:

Integral promotion with sign extension followed by left truncation.


Long version:

Whether char is signed or unsigned depends on the implementation. Working backwards, 0xFF00 suggests that on your platform char is signed. I will also assume that on your platform char is 1 byte, short is 2 bytes, and int is 4 bytes.

Initial values:
signed char cA = 1000 0000 (0x80) (-128)
unsigned char ucB = 1000 0000 (0x80) (128)

Expression as written:
cA + (char)ucB

Arithmetic in C doesn't use anything smaller than an int. In an expression whose operands are all char or short, on a platform where char is signed, every operand is always promoted to int.

Expression as evaluated:
(int)cA + (int)(char)ucB

Before moving on to each operand's promotion to int, let's take a close look at (char) ucB .

The result of casting ucB to char is unpredictable for a couple of reasons. First, is char signed or unsigned? As mentioned earlier, that depends on the implementation. If char is unsigned, then your cast of ucB has no effect, because the original type and the new type are identical. If, however, char is signed (as appears to be the case here), you will be casting from an unsigned type to a signed type of identical width. Even though both types use the same number of bits, since a bit is lost to the sign, the new, signed type cannot represent the full range of values of the original type. Obviously, this is also true when the new type is narrower. In both cases, ANSI says that the result of converting from an unsigned type to a signed type of equal or lesser width is implementation-defined.

Your implementation seems to have left the original bit-field as is. So before and after the cast, unsigned char to signed char, ucB still holds 1000 0000 (0x80).

Before adding, each value is promoted to int. Promoting a signed type to a wider signed type is done through sign-extension. cA and ucB, now both of identical type and value, are promoted from signed char to signed int:
1000 0000 (0x80) (-128) --> 1111 1111 1111 1111 1111 1111 1000 0000 (0xffffff80) (-128)

Finally, we can perform some arithmetic:

Code:
  1111 1111 1111 1111 1111 1111 1000 0000    (0xffffff80) (-128)
+ 1111 1111 1111 1111 1111 1111 1000 0000    (0xffffff80) (-128)
=========================================
1 1111 1111 1111 1111 1111 1111 0000 0000    (0xffffff00) (-256)


The carry bit (in red) is ignored.

The assignment to usC requires converting a signed type to a narrower unsigned type, int to unsigned short. This is done through left truncation:
1111 1111 1111 1111 1111 1111 0000 0000 (0xffffff00) (-256) --> 1111 1111 0000 0000 (0xff00) (65280)

Keep in mind that due to the implementation-defined situations mentioned above, a different platform can yield different results.

posted on 2012-08-17 08:05  micky.zhou  阅读(2202)  评论(0编辑  收藏  举报

导航