【问题标题】:Displaying an integer to hex in C在C中将整数显示为十六进制
【发布时间】:2013-02-26 13:33:32
【问题描述】:

我在 C 类中有这部分代码:

int i;
    for (i=0;i<val;i++)
        mdl_print ("%u ", rec->payload[i]);
    mdl_print ("\n");

变量 rec->payload 是 uint8_t 类型。我会用十六进制表示法打印它。

我该怎么办?谢谢。

【问题讨论】:

  • 大概mdl_print() 采用printf() 采用的任何格式字符串?
  • 是的 ;) 我为个人使用重写了
  • 我不明白这个问题如何值得否决。如何正确地将 uintN_t 转换为十进制数字字符串还不是很清楚,这一问题的错误答案数量证明了这一点。读过 7.21.6.1 p8 和 p9 的人写了多少答案?显然,没有。

标签: c casting integer printf hex


【解决方案1】:

请注意,如 n1570.pdf 的第 7.21.6.1p9 节所述,提供 uint8_tint(其中 printf 应为 unsigned int)是未定义的行为:“如果任何参数不是正确的类型相应的转换规范,行为未定义。”根据 7.21.6.1p8,%x 告诉 printf 期待 unsigned int。确保将uint8_t 显式转换为(unsigned int),或使用&lt;stdint.h&gt; 中的PRIx8 宏。

#include <assert.h>
#include <stdint.h>
#include <stdio.h>

int main(void) {
    uint8_t foo = 42;
    /* These two printfs are equivalent: */
    printf("Hex for %02u: %02x\n", (unsigned int) foo, (unsigned int) foo);
    printf("Hex for %02" PRIu8 ": %02" PRIx8 "\n", foo, foo);
    return 0;
}

【讨论】:

  • 阅读同一文档的第 7.20 节(整数类型)。 uint8_t is 是一个有效的整数类型,因此 not 不会导致 UB
  • @JensGustedt 好的,您能否或可修改的左值再进一步解释一下。 7.21.6 p8 说 x 接受 unsigned int 参数。 7.20.1.1(2 &3) 声明 typedef 名称 uintN_t 指定无符号 int 类型,并且实现提供 8 位作为宽度之一。那么uint8_t 是如何不是 无符号整数的呢?转换为signed int 的位置在哪里?并且显式类型转换解决了这个问题?
  • 对于隐式转换,只要所有值都适合它,所有窄类型都会转换为int。顺便说一句,只要在算术表达式中使用窄类型或将其传递给没有原型的函数(例如 printf),就会应用此转换。
  • @Mike 7.20.1.1p2 提到“无符号整数类型”,不是unsigned int”。 7.21.6p8 特别提到“unsigned int”。是sizeof (uint8_t) == sizeof (unsigned int)? No. 6.5.2.2p6 暗示 整数提升 应用于函数调用的参数,如 printf。 “如果一个 int 可以表示原始类型的所有值(受宽度限制,对于一个位域),则该值将转换为一个 int; ...” 所以参数实际上是一个 int.
【解决方案2】:

首先你的标题是错误的......Casting integer to hex in C 转换意味着类型更改,十六进制是数字系统而不是类型。您“以十六进制显示整数”而不是“强制转换”。如果您不明白其中的区别,请要求澄清。

就显示而言,这取决于您希望结果的样子。我通常使用的一种捷径是:

mdl_print("%#x ", rec->payload[i]);

将值显示为:

0xA6

这个语法的警告是它不适用于 0,你不会得到 0x0 只是 0。所以另一种选择是:

mdl_print("0x%x ", rec->payload[i]);

这会将值显示为0xA60x0 或任何可能的值。当然,如果您不想要 0x 部分,您可以随时这样做:

mdl_print("%x ", rec->payload[i]);

无符号 8 位数字的最大值(十六进制)是 0xFF,因此如果您希望它们都显示相同的“宽度”,您也可以使用大小说明符:

mdl_print("%02x ", rec->payload[i]); // or mdl_print("0x%02x, rec->payload[i]); 
                                     // or whatever you picked

【讨论】:

    【解决方案3】:

    使用“%x”,所以:

    mdl_print("%x", rec->payload[i]);

    这会给你一个十六进制数字,它是“必要的长度”。如果您想要一个固定长度,请使用“%02x”作为用零填充的两位数字。

    【讨论】:

    • 如果参数的功能类似于标准 C:mdl_printf("%x", (unsigned int) rec-&gt;payload[i]); 中的格式化打印,则该参数应显式转换为 unsigned int。来自 n1570.pdf 的 7.21.6.1p8 的证明:“unsigned int 参数转换为 ... unsigned hexadecimal notation (x or X)”。
    【解决方案4】:

    如果 mdl_print() 像标准 C 函数 printf() 一样工作,请尝试以下操作:

    printf( "%02x", (int) rec->payload[i] );
    

    以十六进制编写的基本 printf 格式化代码是 %x。 "02" 表示用 '0' 填充数字,直到它有两个字符宽,这就是您通常打印 int8 的方式。

    许多自定义输出函数都以这种方式遵循 printf 的格式,因为 C 程序员非常熟悉它。您可以在其手册页上阅读有关 printf 的更多信息:http://linux.die.net/man/3/printf

    【讨论】:

      【解决方案5】:

      快速简单:

      print("%x", (int)(rec->payload[i]));
      

      要以 0x05 格式显示,请使用:

      print("0x%02x", ...)
      

      改为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-28
        • 2011-08-11
        • 2010-10-16
        • 2015-02-14
        • 2017-08-12
        • 2021-03-04
        相关资源
        最近更新 更多