c - 字符范围是正数,那么如果我在其中存储一个整数,它应该打印一个介于(0-255)之间的值。为什么输出是-24
问题描述
'''
void main()
{
int i=1000;
char c='A';
c=i;
printf("%d",c);
}
'''
输出为-24
为什么当字符范围为(0-255)时输出
解决方案
在解释该行为时,需要考虑以下事项:
首先,在一个任务c=i
中
int i=1000;
char c='A';
c=i;
我们需要考虑i
转换为c
之前赋值的类型。在线 C99 标准草案中定义了积分转换:
6.3.1.3 有符号和无符号整数
1 当整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则不变。
2 否则,如果新类型是无符号的,则通过在新类型中可以表示的最大值的基础上反复加减一来转换值,直到该值在新类型的范围内。60)
3 否则,新类型是有符号的,值不能在其中表示;结果是实现定义的,或者引发了实现定义的信号。
所以有必要知道是否char
是单数整数类型。这可能因编译器而异,但您的编译器似乎默认认为char
类型signed char
。
在 的情况下signed char
,“结果是实现定义的”,我们需要查看编译器的规范。
一个常见的实现是整数值 1000,它在二进制中00000011 11101000
被截断为 8 位并存储在 char 值中。
那么11101000
对于 a 的含义是在类型的表示中signed char
定义的:
6-2-6-2 整数类型
2 对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;signed char 不应有任何填充位。应该有一个符号位。作为值位的每个位应与相应无符号类型的对象表示中的相同位具有相同的值(如果有符号类型中有 M 个值位,无符号类型中有 N 个值位,则 M <= N)。如果符号位为零,则不应影响结果值。如果符号位为 1,则该值应通过以下方式之一进行修改:
符号位为 0 的对应值取反(符号和幅度);
符号位的值为 -(2M)(二进制补码);
符号位的值为 -(2M- 1) (反码)。
其中哪一个适用是实现定义的,因为...
同样,结果由编译器的实现定义;但常见的解释是二进制补码,将最高有效位解释为符号位:
在您的情况下, 的 8 位11101000
是一个符号位(设置)和余数的 7 位;余数1101000
是 104;二进制补码中的实际值为 -(127-104+1),即 -24。
注意,不清楚结果是-24;其他编译器可能会产生不同的结果。
当您使用格式说明符“%d”打印签名字符值时,还需要考虑一个步骤:
printf("%d",c)
这意味着,负值signed char
被提升为int
类型;但这将产生“相同”的负值。我省略了对“提升”的解释以及为什么printf
要提升其中的论点。
推荐阅读
- java - 为什么我在分页的 recyclerview 上收到 ANR(应用程序无响应)?
- django - “必须提供查询字符串。” 石墨烯-蟒蛇
- ansible - 关于大规模部署环境下ansible的forks配置
- webpack - 使用 npm run watch 降低 PhpStorm 性能
- android - 如何监控片段更改?
- php - 如何将响应存储在价值中?
- node.js - 用于调用 REST API 的 Nodejs 和 Express 代理设置
- sql - 通过 id 将行聚合为一个 - postgres
- javascript - 平滑滚动到 id 而不使整个身体滚动
- android - 无法在签名 APK 上访问 Google Drive(在 debug-apk 上运行良好)