【问题标题】:print single byte after typecasting to char类型转换为 char 后打印单个字节
【发布时间】:2017-06-27 09:30:05
【问题描述】:

我正在从套接字接收一些数据。
之后,我想在接收到的 char 数组中打印一个字节。

下面是我使用的代码:

char buf[100];                                                                
int i = 0;                                                                    
while (1)                                                                     
{                                                                             
    rc = recv(socket_fd, buf, sizeof(buf), 0);                                  

    if (rc > 0)                                                                 
    {                                                                           
        printf("Pos1 = %x.\n", (char)buf[17]);   
        printf("Pos2 = %x.\n", (char)buf[22]);   
    }     
}

但这会打印出 4 个字节。如果我将字符类型转换为 unsigned char,则会打印单字节。那么这两种类型转换有什么区别,导致打印的字节数不同。

输出:

Pos1 = 1

Pos2 = ffffff83

【问题讨论】:

  • 你为什么使用%x?你需要十六进制值吗?
  • 是的。我希望以十六进制打印值。
  • 分享您的输出。你是如何确定它正在打印 4 个字节的?
  • %x 用于unsigned int。传递负字符会导致未定义的行为
  • 你怎么知道rc > 22,所以buf[22]有有效数据?您只测试是否至少有 1 个char 读取。

标签: c casting char unsigned-char


【解决方案1】:

如果您只想打印 2 个半字节,请使用:

printf("Pos1 = %02x.\n", (unsigned)(unsigned char)buf[17]);
/*              ^^                           */
/* Print 2 nibbles with 0 prefix if required */

在某些系统上,char 的行为可能与 signed char 相同,您会看到前面有 ff 以显示负数。因此,您必须在此类系统上将您的 buf[i] 转换为 unsigned char。第二个无符号用于匹配带有说明符%x的参数类型

Working example

【讨论】:

  • 我试过了,但结果是一样的。它也打印 4 个字节。
  • 对不起,我盲目地复制了选角。确保你投到unsigned char
  • 是的。它前面带有 ffffff。我的输出就像 Pos2 = ffffff83。
  • 试试printf("Pos1 = %02x.\n", (unsigned)(unsigned char)buf[22]);
  • 或者,更短; buf[22] & 255U
【解决方案2】:

如果你在 C stdio 库中找到 printf 的参考

说明符“x”打印一个无符号十六进制整数。

首先,打印函数需要一个整数值。

在您的示例中,您正在转换为签名字符。

看起来正在发生的事情是,当您将变量转换为有符号字符时,如果该值超过 127 (0X7F),则设置的有符号位将扩展为 4 字节整数实体。另一方面,如果该值为正(0 到 127),则输出(尽管从技术上讲是一个 unsigned int 值)将与 unsigned char cast 相同。

例如 128 (0x80) 将显示为 FFFFFF80 如果您投射为 Char 转换为无符号字符时为 80。

另一方面,127 将显示为 7F 与任一演员表。

因此,在使用 printf 时,要打印的变量类型应与说明符类型匹配。

【讨论】:

    【解决方案3】:

    那么这两种类型转换有什么区别,即导致字节数不同?

    传递给函数printf 的每个输入参数在被压入堆栈之前都会“扩展”为 4 或 8 个字节(取决于其类型)。

    当您传递类型为signed 的输入参数时,符号位是“保留的”。

    例如,signed char 0x89 扩展为 signed int 0xFFFFFF89

    unsigned char 0x89 扩展为unsigned int 0x00000089


    请注意,上面的答案取决于平台。

    我假设在您的平台上:

    • CHAR_BIT 是 8
    • sizeof int 是 4
    • sizeof double 是 8

    关于printf 输入参数的AFAIK:

    • 小于int 的整数参数扩展为int
    • 小于double 的非整数参数扩展为double

    【讨论】:

      【解决方案4】:

      告诉printf,你正在传递unsigned int的一半

      printf("Pos1 = %hhx.\n", (unsigned char) buf[17]);
      

      【讨论】:

        猜你喜欢
        • 2023-01-07
        • 1970-01-01
        • 2019-01-31
        • 2015-01-16
        • 2012-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-22
        相关资源
        最近更新 更多