【问题标题】:unexpected behavior on casting char to int将 char 转换为 int 的意外行为
【发布时间】:2017-03-15 16:00:50
【问题描述】:

我在将char 转换为unsigned int 时遇到意外行为。有时剩余的位用 0 填充,有时用 1 填充。

在 gcc 4.9.2 上测试的一个简单程序

unsigned int test_1 = 0x01;
unsigned int test_2 = (char)(0x01);
unsigned int test_3 = 0xc3;
unsigned int test_4 = (char)(0xc3);

输出是

00000000 00000000 00000000 00000001 
00000000 00000000 00000000 00000001 
00000000 00000000 00000000 11000011 
11111111 11111111 11111111 11000011

我希望“空白”位填充 0 而不是 1。

预期输出:

00000000 00000000 00000000 00000001 
00000000 00000000 00000000 00000001 
00000000 00000000 00000000 11000011 
00000000 00000000 00000000 11000011

完整代码如下:

#include "stdio.h"

#define binary_p( x ) printBits(sizeof(x),&x)

void printBits(size_t const size, void const * const ptr)
{
    unsigned char *b = (unsigned char*) ptr;
    unsigned char byte;
    int i, j;

    for (i=size-1;i>=0;i--)
    {
        for (j=7;j>=0;j--)
        {
            byte = (b[i] >> j) & 1;
            printf("%u", byte);
        }

            printf(" ");
    }
     puts("");
}

int main(int argc, char *argv[])
{
    unsigned int test_1 = 0x01;
    unsigned int test_2 = (char) (0x01);
    unsigned int test_3 = 0xc3;
    unsigned int test_4 = (char) (0xc3);

    binary_p(test_1);
    binary_p(test_2);
    binary_p(test_3);
    binary_p(test_4);

    return 0;
}

【问题讨论】:

  • c/c++ 是 UB..
  • 改用(unsigned char)!结果是一样的吗?
  • 你的编译器根据标准做了正确的事情,但显然不是你想要的。你想发生什么?
  • 您期望什么行为以及为什么?
  • 似乎char 是签名的,而到unsigned int 的转换是签名扩展的。如果您转换为带符号的int,您应该看到intchar 的负值相同。您可以改用 unsigned char,正如 Iharob 上面建议的那样。

标签: c type-conversion


【解决方案1】:

在这种情况下:

unsigned int test_3 = 0xc3;

常量0xc3 的类型为int。它的值 (195) 在 int 的正数范围内,因此当它通过赋值转换为 unsigned int 时,它会保留该值。

至于这种情况:

unsigned int test_4 = (char)(0xc3);

该值首先转换为char。假设char 是 8 位并且 2 的补码表示用于负数,则此表示属于负数范围 (-61)。所以当它转换成更大的类型时,添加的额外位被设置为 1 以保持相同的负值。

【讨论】:

  • 详细说明:即使“char 是 8 位和 2 的补码表示”,195 到 8 位有符号 char 的转换也是实现定义的行为(或发出信号)。常见但未指定的 ID 行为导致 (char)(0xc3) --> -61
【解决方案2】:

试试

(unsigned char)(0xc3)
(unsigned char)(0xc3)

而不是

 (char)(0x01)
 (char)(0xc3)

这应该可以解决问题

【讨论】:

    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2011-02-25
    • 2015-11-23
    • 2015-12-18
    • 2017-04-25
    相关资源
    最近更新 更多