gpt4 book ai didi

安全地将字符转换为整数

转载 作者:太空狗 更新时间:2023-10-29 16:07:30 25 4
gpt4 key购买 nike

当我让 char 保存一些整数(例如 23),并想将其转换为更大的整数(int)时,我听说可能存在一些问题,因为编译器必须决定是将 char 解释为 signed 还是 unsigned?这是真的?会因此出现问题吗?以及如何避免这种情况?

换句话说(我不确定下面的公式是否等同于上面的公式),这样的转换会出现什么问题:

   char someCharVal = //...
int x = someCharVal;

以及如何避免它们?

附言。欢迎“傻瓜”的解释

最佳答案

问题是,简单明了,符号扩展错误地将无符号值视为有符号值。

让我们检查 8 位和 16 位二进制补码中 5-5 的位模式:

      8-bit          16-bit
========= ===================
+5 0000 0101 0000 0000 0000 0101
-5 1111 1011 1111 1111 1111 1011

将一个数从 8 位转换为 16 位时,最高位向左扩展。换句话说,8 位数字左边的零位将延伸到 16 位数字的上半部分。

同样,最高位中的一位将向左延伸。

这是 C 扩展其有符号数的方式(无论如何,对于二进制补码,二进制补码和符号幅度编码是另一回事,但现在很少有实现使用它们)。

因此,如果您要将 signed char 转换为 signed int,或将 unsigned char 转换为 unsigned int,没有问题。 C 会给你正确的值。

当您切换到或从 signed 类型切换到其他类型时,问题就存在了。,问题是底层数据的处理方式可能与您预期的不同。

例如,请参见以下代码,具有 8 位 char 和 32 位 int 类型:

#include <stdio.h>

int main (void) {
printf ("unsigned char 50 -> unsigned int %11u\n", (unsigned char)50);
printf ("unsigned char -50 -> unsigned int %11u\n", (unsigned char)-50);
printf ("unsigned char 50 -> signed int %11d\n", (unsigned char)50);
printf ("unsigned char -50 -> signed int %11d\n", (unsigned char)-50);

printf (" signed char 50 -> unsigned int %11u\n", ( signed char)50);
printf (" signed char -50 -> unsigned int %11u\n", ( signed char)-50);
printf (" signed char 50 -> signed int %11d\n", ( signed char)50);
printf (" signed char -50 -> signed int %11d\n", ( signed char)-50);

return 0;
}

这个输出显示了各种转换,带有我的注释:

unsigned char  50 -> unsigned int          50
unsigned char -50 -> unsigned int 206 # -50 unsigned is 256-50
unsigned char 50 -> signed int 50
unsigned char -50 -> signed int 206 # same as above
signed char 50 -> unsigned int 50
signed char -50 -> unsigned int 4294967246 # sign extend, treat as unsigned
signed char 50 -> signed int 50 (2^32 - 50)
signed char -50 -> signed int -50

第一个不寻常的情况是第二行。它实际上采用 signed char -50 位值,将其视为 unsigned char,并将其扩展为 unsigned int,正确保留其无符号值 206。

第二种情况做同样的事情,因为 signed int 能够保存整个范围的 unsigned char 值(在这个实现中)。

第三种不寻常的情况将 -50 扩展为 signed int,然后将底层位模式视为 unsigned int,让您大的正值。

请注意,当值的“符号”不变时,没有问题。

C 标准不强制要求 char 类型默认具有什么符号,它可以是有符号的或无符号的。因此,如果您想要真正可移植的代码,它不应包含任何“裸”char 类型。

如果您想使用带符号的值,请使用带符号的值。这包括显式使用signed char 而不是char。同样,如果您想使用无符号值,请在所有地方使用无符号(包括显式使用 unsigned char)。除非您完全知道会发生什么,否则不要从已签名升级到未签名或反之亦然。

关于安全地将字符转换为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22905162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com