我知道已经回答了非常类似的问题,但我相信它不能解决我的问题。
unsigned char aaa = -10;
unsigned int bbb = (unsigned int)-5;
unsigned int ccc = (unsigned int)20 + (unsigned int)bbb;
printf("%d\n", aaa);
printf("%d\n", ccc);
Run Code Online (Sandbox Code Playgroud)
上面的代码打印aaa = 246(这是我所期望的),但这ccc = 15意味着unsigned int一直被视为签名。即使尝试可能过时的类型转换,我也找不到对此的解释。
unsigned char aaa = -10;
该int值将通过重复相加-10进行转换,直到结果在 的范围内。您的系统上很可能有 8 位,这意味着. 也是,在范围之内。所以。unsigned charUCHAR_MAX + 1[0, UCHAR_MAX]charUCHAR_MAX = 2**8 - 1 = 255-10 + UCHAR_MAX + 1246aaa = 246
unsigned int bbb = (unsigned int)-5;
添加,假设有 32 位,-5则结果为。UINT_MAX + 1intbbb = 4294967291
unsigned int ccc = (unsigned int)20 + (unsigned int)bbb;
无符号整数溢出“环绕”。那么就20 + 4294967291 = 4294967311更大了UINT_MAX = 2**32 - 1 = 4294967295。所以我们减去UINT_MAX+1直到我们在 range 内[0, UINT_MAX]。所以4294967311 - (UINT_MAX+1) = 15。
printf("%d\n", aaa);
该代码很可能没问题。最有可能在您的平台上,在传递给可变参数函数参数之前unsigned char被提升为。int有关促销的参考,您可以阅读cppreference 隐式转换。因为%d期望intandunsigned char被提升为int,所以代码没问题。[1]
printf("%d\n", ccc);
此行会导致未定义的行为。ccc具有类型unsigned int,而%d printf格式说明符需要一个signed int. 因为您的平台使用两位补码来表示数字,所以这只会导致printf将这些位解释为有符号值,无论如何15。
[1]:理论上有可能unsigned char具有与 一样多的位int,因此unsigned char将被提升为unsigned int而不是int,这也会导致那里出现未定义的行为。
| 归档时间: |
|
| 查看次数: |
105 次 |
| 最近记录: |