【问题标题】:reverse hex number into a string将十六进制数字反转为字符串
【发布时间】:2021-08-01 22:16:21
【问题描述】:

我想转换 unsigned long long

0xabcd1234

到这个字符串

3412cdab

*我们希望保留前导零,例如 0x1 将转换为该字符串“01000000”,而 0x123 将转换为“23010000”

现在我成功编写了执行此操作的代码,但我想知道是否有更简单的方法

char* encode_long_long_hex(unsigned long long integer, char* out, 
                           int  len, size_t *out_len)
{
    static char encode_hex_char_arr[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',  
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    char* dst = out;
    unsigned idx = count_long_long_digits(integer); //return number of digits
    
    while (idx && dst < out + len)
    {
        idx -= 2;
        
        *dst = encode_hex_char_arr[(integer & 0xF0) >> 4];
        dst += sizeof(char);
        
        *dst = encode_hex_char_arr[integer & 0x0F];
        dst += sizeof(char);
        
        integer >>= 8;
    }

    *out_len = (int) (dst - out);
    
    return dst;
}

谢谢!

【问题讨论】:

  • 0x12345 怎么样。预期的输出是什么?
  • char *string="3412cdab";。更简单 更严重的是,为什么不printf(string, "%02X%02X%02X%02X", lValue&amp;0xFF, lValue&gt;&gt;8&amp;0xFF, lValue&gt;&gt;16&amp;0xFF, lValue&gt;&gt;24&amp;0xFF); ? (但要注意整数的字节序)
  • @Zilog80 实际上字节序在这里并不重要,您发布的代码(与我的回答一致)与字节序无关。
  • @EugeneSh。你是对的,对不起,我错过了你的答案(我指出 Endianess 是 long long 值的起源
  • @ 0_______________ 它 0x12345 --->。 45230100

标签: c bit-manipulation bit


【解决方案1】:

我猜您要问的正式问题是“如何将表示为十六进制的 int 从大端转换为小端”(反之亦然)

如果是这样,那么正式的答案将是“解析十六进制,转换字节序,格式化回十六进制”,或者换句话说 format(convert(parse(input))),或者在 C 中:

#include <stdlib.h>
#include <byteswap.h>
#include <stdio.h>

char output[11];
sprintf(output, "0x%x", bswap_32(strtol(input, NULL, 0)));

// Or without "0x" in both input and output:

char output[9];
sprintf(output, "%x", bswap_32(strtol(input, NULL, 16)));

【讨论】:

  • 不错的收获。我一直在寻找 __builtin_bswap64,但它是 GCC 内置的。 htobe64 也许,但不是很便携。 bswap_32 不只是 linux 吗?
  • strtoull()strtol() 更有意义实现“想要转换 unsigned long long”。
【解决方案2】:
#include <stdio.h>

void toHexReverse(unsigned long long val, char *buff)
{
    static const char hex[] = "0123456789ABCDEF";

    while(val)
    {
        buff[1] = hex[val % 16];
        val /= 16;
        buff[0] = hex[val % 16];
        val /= 16;
        buff += 2;
    }
    *buff = 0;
}


int main(void)
{
    char buff[20];
    toHexReverse(0xabcd1234, buff);
    printf("%s\n", buff);
}

https://godbolt.org/z/37zvM75MK

【讨论】:

    【解决方案3】:

    有一种更简单的方法是利用sprintf 为您完成从数字到字符的转换:

    #include <stdio.h>
    
    int main(void) {
        unsigned x = 0xabcd1234;
        char s[40];
        sprintf(s, "%02x%02x%02x%02x", 
            x & 0xFF,
            (x >> 8) & 0xFF,
            (x >> 16) & 0xFF,
            (x >> 24) & 0xFF
        );
        
        printf("%s\n", s);
        // your code goes here
        return 0;
    }
    

    这会将原始数字按字节“输入”到sprintf,后者会将这些数字格式化为十六进制。 (注意,我在这里使用了unsigned 类型,而不是long long,因为您的示例中的数字适合它在我的平台上。如果您需要更大的类型,您也可以采用这种方法)。

    Demo

    【讨论】:

    • 对于long long 它不会更简单 - 大量参数
    • @0___________ 更长,是的,但我仍然认为更简单 - 不涉及任何逻辑 - 只是机械工作:)
    • 他想将 unsigned long long 0xabcd1234 转换为 "3412cdab" 而不是 "3412cdab00000000" 就像您的代码中那样,如果我们将其扩展为 unsigned long long。简直是错误的解决方案。想象一下,即使在您的示例中,他也想转换0x12godbolt.org/z/Pa18b95E5
    • 我的意思是0x1234
    • @0___________ 你可能是对的,不过操作人员可能想澄清一下
    猜你喜欢
    • 2018-11-02
    • 2018-01-31
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    • 2018-01-22
    • 2019-01-17
    • 2020-11-07
    相关资源
    最近更新 更多