【问题标题】:Looking for macro converting decimal value into its hex representation寻找将十进制值转换为其十六进制表示的宏
【发布时间】:2013-12-30 00:59:58
【问题描述】:

在我的一个项目中,我将当前版本定义为十进制值,看起来像这样:

#define MINOR_VERSION 13

为了能够在要求时输出版本,我需要将十六进制表示形式转换为字符串。目前我正在使用 sprintf(),它基本上看起来像这样:

char buffer[3];
sprintf(buffer, "%2x", MINOR_VERSION);
// output buffer

这有几个缺点,其中之一是增加了代码大小,因为需要包含 sprintf()。此外,该值是在运行时计算的,无论如何这都是浪费精力。这两个问题对我来说都很重要,因为我在这里使用微控制器。

也许我错过了完全显而易见的,但我想不出一个漂亮而干净的宏来为我做转换。原则上,我需要一种在编译期间将13 转换为十六进制表示(2 位,通常没有前面的 0x)0d 的方法。

你有什么建议?

【问题讨论】:

  • 这必须是宏吗?你能用一个 constexpr 函数吗?
  • 有什么理由必须使用二进制整数吗?你可以只使用一个字符串吗?两者都需要吗?
  • 我很困惑——上面没有产生十六进制表示。
  • @razeh:我可能不应该用“c++”标记这个问题,因为实际上我正在使用普通的旧 C。所以,看起来,constexpr 不是一个选项。
  • @Fiddling Bits:“只使用字符串”是什么意思?不确定我是否在关注你...

标签: c macros hex decimal


【解决方案1】:

翻转问题,并将版本定义为十六进制。当您需要将其用作字符串时,请使用来自here 的答案将其转换为字符串。然后你可以这样做:

#include <stdio.h>

#define VERSION 0xd
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

int main() {
  printf("hello " TOSTRING(VERSION) "\n");
  printf("%d\n", VERSION);
}

【讨论】:

  • 这可能有效,但它不像我最初想要的那样方便,因为在更改版本号时您必须以十六进制“思考”:(。谢谢!
【解决方案2】:

我假设您将手动增加 MINOR_VERSION。如果是这样,为什么要麻烦让宏为您将其转换为字符串。只需在定义中包含二进制和字符串形式的这个数字:

#define MINOR_VERSION_BIN (13)
#define MINOR_VERSION_STR ("D")

我了解您可能会发现这样做有风险,例如,您可以增加一个但不能增加另一个,但是,预处理器的功能非常有限。它更适合替换,而不是转换。

【讨论】:

  • 从不同的角度解决问题很好,但我发现如果我重复版本字符串之类的东西,最终我会把它搞砸,改变一个而不是另一个.
  • 嗯,这当然是一种可能性,但是我不太喜欢它,因为它迫使我更新两个值以用于版本提升。此外,您总是可以争辩说,这两个值会随着时间的推移而出现分歧,因为有人会忘记和/或忽略它。
【解决方案3】:

您可以手动创建字符串:

#define HEX_DIGIT(digit) "0123456789ABCDEF"[(digit)]
#define MAKE_HEX(value) HEX_DIGIT((value) < 16? (value): ((value)/16)%16), \
                        HEX_DIGIT((value) < 16? 16: (value)%16),           \
                        0

#define MINOR_VERSION_BIN 13
char const version[] = { MAKE_HEX(MINOR_VERSION_BIN) };

【讨论】:

    【解决方案4】:

    相信编译器。如果您绝对坚持在编译时解决它,请使用常量表达式。

    char MINOR_VERSION_STR[3] { 
        '0'+(MINOR_VERSION >>4)&0xF,
        '0'+(MINOR_VERSION)&0xF, 
        0 };
    

    这将适用于次要版本 63 —— 尽管不可否认的是前导零。我认为,如果您超过了 64 个次要版本,那么是时候发布另一个主要版本了。或者,如果你真的想要,你可以通过添加 nybbles 向上扩展

    如果前导 0 困扰您,您可以使用条件表达式——同样,优化器应该能够在编译时解析——

    char MINOR_VERSION_STR[3] { 
        MINOR>VERSION > 15 ? '0'+(MINOR_VERSION >>4)&0xF : '0'+(MINOR_VERSION)&0xF,
        MINOR>VERSION > 15 ? '0'+(MINOR_VERSION)&0xF : 0, 
        0 };
    

    不需要宏,当然如果你认为你会在其他地方使用它,你可以把它变成一个宏。

    或者,不要使用 sprintf,而是为此目的编写一个小的专用函数。正如她所展示的那样,它可以非常小而且非常快。

    将 C 视为高级汇编程序。这些库很棒,但是当库不能满足您的需求时,请自行调整。

    【讨论】:

      【解决方案5】:

      master将 MINOR_VERSION 文本定义为所需(十六进制)格式的字符串。
      让 MINOR_VERSION 的int 版本由此派生。

      #define MINOR_VERSION_S " D"
      #define MINOR_VERSION strtol(MINOR_VERSION_S, 0, 16)
      

      注意:OP 的sprintf(buffer, "%2x", MINOR_VERSION); 的结果是" D"

      【讨论】:

        猜你喜欢
        • 2014-02-05
        • 1970-01-01
        • 1970-01-01
        • 2011-07-28
        • 1970-01-01
        • 2018-02-17
        相关资源
        最近更新 更多