首页 > 解决方案 > 字符范围是正数,那么如果我在其中存储一个整数,它应该打印一个介于(0-255)之间的值。为什么输出是-24

问题描述

'''

void main()
{
   int i=1000;
   char c='A';
   c=i;
   printf("%d",c);
}

'''

输出为-24

为什么当字符范围为(0-255)时输出

标签: carrayscharoutputsigned

解决方案


在解释该行为时,需要考虑以下事项:

首先,在一个任务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要提升其中的论点。


推荐阅读