【问题标题】:typecasting unsigned char and signed char to int in C在C中将unsigned char和signed char类型转换为int
【发布时间】:2020-06-20 21:55:01
【问题描述】:
int main()
{
  char ch1 = 128;
  unsigned char ch2 = 128;
  printf("%d\n", (int)ch1);
  printf("%d\n", (int)ch2); 
}

第一个 printf 语句输出 -128 和第二个 128。根据我的说法,ch1 和 ch2 将具有相同的二进制表示存储的数字:10000000。所以当我将两个值都转换为整数时,它们最终是如何成为不同的值的?

【问题讨论】:

  • char ch1 = 128; 导致有符号溢出,因为 127 是适合 8 位 2 的补码有符号字符的最大值。实际上,它是char ch1 = -128;

标签: c


【解决方案1】:

首先,char 可以是signedunsigned,这取决于编译器的实现。但是,当你得到不同的结果时。然后,您的编译器会将char 视为signed

signed char 只能保存从 -128 到 127 的值。因此,有符号字符的值 128 会溢出到 -128

unsigned char 可以保存从 0 到 255 的值。因此,值 128 保持不变。

【讨论】:

    【解决方案2】:

    您的基本错误是误解了 C 中的强制转换(或任何转换)的作用。它不会重新解释位。这纯粹是对 values 的操作。

    假设普通 char 已签名,ch1 的值为 -128,ch2 的值为 128。-128 和 128 都可以在 int 中表示,因此转换不会改变它们的值。 (此外,编写它是多余的,因为 default Promotions 会自动将等级低于 int 的类型的可变参数转换为 int。)转换只能更改表达式的值值在目标类型中不可表示

    【讨论】:

    • 你能告诉我“它不会重新解释位。它纯粹是对值的操作”是什么意思?将一个类型转换为其他类型究竟意味着什么,尤其是在这种情况下?
    • 强制转换是在类型之间产生显式转换的运算符。转换也可以在很多上下文中隐式发生。当我说它“不重新解释位”时,我的意思是 C 中的所有转换都是根据值定义的。如果被转换的值在目标类型中是可表示的,则该值不变,并且转换的唯一影响是类型的变化(这可能会影响它如何参与更大的表达式)。如果该值在目标类型中不可表示,则有关于如何产生结果的规则;在某些情况下,它是 impl 定义的。
    【解决方案3】:

    unsigned char 的值可以是 0255signed char 的值可以是 -128127。在您的编译器中将signed char 设置为128 可能会环绕到可能的最低值,即-128

    【讨论】:

    • 是的,我知道签名字符会将其存储为 -128。但是,如果我将此 char 类型转换为 int,那应该保持 -128 吗?
    • 是的。 (int)(char)128 == -128 为真(在您的平台上)。
    • A char can have a value of 0-255.,这不是正确的。你应该说:An unsigned char can have a value of 0-255.。因为 char 本身可以是有符号或无符号的,具体取决于编译器实现。 C 规范没有说明 char 应该是有符号的还是无符号的。 (我个人遇到了两个行为不同的编译器)
    • @KamilCuk 怎么样?因为我认为有符号和无符号字符的二进制表示形式都是 10000000。所以现在如果我将其类型转换为 int,编译器是否会在有符号字符的情况下将 1 放在 msb 之后,在无符号的情况下将 0 放在?
    • @Youssef13:同样,您的答案应该是 unsigned char 的值至少可以是 0 到 255。此外,是否将 128 转换为有符号的 char产生 -128 是实现定义的。 char 可能已签名或未签名,但它绝不是 signed charunsigned char;它仍然是一个独特的类型。
    【解决方案4】:

    对于初学者来说,这些铸件

    printf("%d\n", (int)ch1);
    printf("%d\n", (int)ch2);
    

    是多余的。你可以写

    printf("%d\n", ch1);
    printf("%d\n", ch2);
    

    因为由于默认参数提升,如果该类型的对象可以表示存储在整数类型对象中的值,那么排名小于 int 类型的整数类型将被提升为 int 类型排名较低。

    根据编译器选项,char 类型可以表现为signed charunsigned char 类型。

    来自 C 标准(5.2.4.2.1 整数类型的大小

    2 如果 char 类型的对象的值被视为有符号 在表达式中使用整数时,CHAR_MIN 的值应为 与 SCHAR_MIN 相同且 CHAR_MAX 的值应相同 与 SCHAR_MAX 一样。否则,CHAR_MIN 的值应为 0,并且 CHAR_MAX 的值应与 UCHAR_MAX 的值相同。 20) 的 值 UCHAR_MAX 应等于 2CHAR_BIT - 1。

    所以默认情况下,使用的编译器似乎将 char 类型视为带符号的 char。

    作为第一个声明的结果

    char ch1 = 128;  
    unsigned char ch2 = 128;
    

    128 的内部表示0x80 被解释为有符号值,因为设置了符号位。而这个值等于-128。

    所以你知道第一次调用 printf 输出的值是 -128

    printf("%d\n", (int)ch1);
    

    第二次调用 printf 时使用了 unsigned char 类型的对象

    printf("%d\n", (int)ch2);
    

    输出值 128。

    【讨论】:

    • @AndreasWenzel 哦,我不专心。:)
    猜你喜欢
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    相关资源
    最近更新 更多