在C语言中将int类型转换为2字节的十六进制值

24

我需要将一个整型数转换成两个字节的十六进制值存储到char数组中,使用C语言。请问应该如何实现?


int数据类型是32位,而2字节的十六进制值是8位。如果您的int大于255,则无法适应您的十六进制值(它将溢出)。您是否意味着有符号/无符号字符而不是int? - invert
1
@wez:int类型不一定是32位。但你的问题很好,他确实需要注意溢出。 - Vicky
这个问题看起来像是一道作业题,是吗?如果是的话,请添加“作业”标签。 - Denilson Sá Maia
@Denilson:"像其他所谓的“元”标签一样,作业标签现在已经不再被鼓励使用。",但是@MikeU,请(像往常一样)遵循一般准则,说明任何特殊限制,展示你迄今为止尝试了什么,并询问具体什么让你感到困惑。 - Roger Pate
15个回答

35

如果您可以使用库函数:

int x = SOME_INTEGER;
char res[5]; /* two bytes of hex = 4 characters, plus NULL terminator */

if (x <= 0xFFFF)
{
    sprintf(&res[0], "%04x", x);
}

你的整数可能包含超过四个十六进制数字的数据,因此先进行检查。

如果不允许使用库函数,则需要手动将其分解成nibble(四位二进制数):

#define TO_HEX(i) (i <= 9 ? '0' + i : 'A' - 10 + i)

int x = SOME_INTEGER;
char res[5];

if (x <= 0xFFFF)
{
    res[0] = TO_HEX(((x & 0xF000) >> 12));   
    res[1] = TO_HEX(((x & 0x0F00) >> 8));
    res[2] = TO_HEX(((x & 0x00F0) >> 4));
    res[3] = TO_HEX((x & 0x000F));
    res[4] = '\0';
}

从看到其他人的答案,似乎他们解释“两个字节的十六进制值”意味着两个nybble,每个由一个字节的十六进制字符表示。我认为它意味着两个数据字节,每个由两个十六进制字符表示。你需要澄清你的意思! - Vicky
感谢 @Vicky 的回答。我用它来构建下面的函数。 - 10SecTom

4

我发现了一个快速的方法,并进行了测试,它可以正常工作。

int value = 11;

array[0] = value >> 8;
array[1] = value & 0xff;

printf("%x%x", array[0], array[1]);

结果是:

000B

这是十六进制中的11。


3
假设int为32位;最简单的方法:只需使用sprintf()。
int intval = /*your value*/
char hexval[5];
sprintf(hexval,"%0x",intval);

现在使用hexval[0]到hexval[3];如果您想将其用作以空字符结尾的字符串,则添加hexval[4]=0;

1
当0xFF < intval时,您将获得不可预测的结果(甚至崩溃)。 - Vovanium
不行。因为sprintf将intval格式化为字符串。 所以0xFFFF(顺便说一下,这不是32位整数的最大值)将是四个F,而这些F不会适合hexval [3],因为您还必须考虑尾随的0。顺便说一句,您不必添加hexval [2] = 0。 - lx.

2

通常我会建议使用其他人推荐的基于sprintf的解决方案。但是当我编写一个需要将数十亿个项目转换为十六进制的工具时,sprintf太慢了。对于这种应用程序,我使用了一个256元素数组,将字节映射到字符串。

这是一个不完整的解决方案,只能转换1个字节,请不要忘记添加边界检查,并确保该数组是静态或全局的,每次检查都重新创建它会降低性能。

static const char hexvals[][3]= {"00", "01", "02", ... "FD", "FE", "FF"};
const char *byteStr = hexvals[number];

2
void intToHex(int intnumber, char *txt)
{    
    unsigned char _s4='0';
    char i=4;
    //intnumber=0xffff;

    do {
        i--;
        _s4 = (unsigned char)  ((intnumber >> i*4 ) & 0x000f);
        if(_s4<10)
            _s4=_s4+48;
        else
            _s4=_s4+55;

        *txt++= _s4;    
    } while(i);     
}
...
char text [5]={0,0,0,0,0};
...

intToHex(65534,text);
USART_Write_Text(text);
....

我已经进行了许多基准测试,你的解决方案是最快的,谢谢。 - thehaxdev

2
char s[5];  // 4 chars + '\0'
int x = 4660;
sprintf(s, "%04X", x);

您可能需要查看 sprintf() 的文档。请注意,此代码并不是非常安全的。如果 x 大于 0xFFFF,最终字符串将会有超过 4 个字符而无法适应。为了使其更加安全,请查看 snprintf()


如果整数是11。我需要得到的两个字节为0B,这是十六进制中的11。 - MBU
错误,这两个字符是半字节,也称为nibble。一个字节(8位,0-255)由2个十六进制字符组成。因此,2个字节由4个十六进制字符组成。每个十六进制字符(或半字节)有4位(0-15,或0-F)。 - Denilson Sá Maia

1

我建议使用snprintf而不是sprintf

#include <stdio.h>

int main()
{
    char output[5];
    snprintf(output,5,"%04x",255);

    printf("%s\n",output);
    return 0;
}

这样更安全,并且几乎在每个编译器中都可用。


0

也许可以尝试这样做:

void IntToHex(int value, char* buffer) {
  int a = value&16;
  int b = (value>>4)&16;
  buffer[0] = (a<10)?'0'+a:'A'-(a-10);
  buffer[1] = (b<10)?'0'+b:'A'-(b-10);
}

这段代码假设字母A到F占据连续的代码点。但是C语言不能保证这一点。 - Bart van Ingen Schenau
你能想到任何实现或编码方式,不需要连续的字母吗? - Alexander Rafferty
仍然是一个不错的答案,也许应该包括Baudot代码和code-UPP。 - Gewure

0
这是一种粗糙的方法。如果我们不能信任ascii值的编码是连续的,我们只需创建一个char中hex值的映射。可能可以优化、整理和美化。还假设我们只捕获最后32位 == 4个十六进制字符。
#include <stdlib.h>
#include <stdio.h>

#define BUFLEN 5

int main(int argc, char* argv[])
{
  int n, i, cn;
  char c, buf[5];
  char hexmap[17] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','.'};

  for(i=0;i<BUFLEN;i++)
    buf[i]=0;

  if(argc<2)
  {
    printf("usage: %s <int>\n", argv[0]);
    return 1;
  }
  n = atoi(argv[1]);
  i = 0;
  printf("n: %d\n", n);

  for(i=0; i<4; i++)
  {
    cn = (n>>4*i) & 0xF;
    c  = (cn>15) ? hexmap[16] : hexmap[cn];
    printf("cn: %d, c: %c\n", cn, c);

    buf[3-i] = (cn>15) ? hexmap[16] : hexmap[cn];
  }
  buf[4] = '\0'; // null terminate it

  printf("buf: %s\n", buf);
  return 0;
}

32位 / 每个十六进制字符4位 = 8个字符。不是4个。 - Chris S

0

使用Vicky上面的答案

typedef unsigned    long    ulong;
typedef unsigned    char    uchar;

#define TO_HEX(i)   (i <= 9 ? '0' + i : 'A' - 10 + i)
#define max_strhex  (sizeof(ulong)*2)

public uchar
*mStrhex(uchar *p, ulong w, ulong n)
{
    ulong i = 0xF;                                  // index
    ulong mask  = i << (((sizeof(ulong)*2)-1)*4);   // max mask (32 bit ulong mask = 0xF0000000, 16 bit ulong mask = 0xF000)
    ulong shift = (w*4);                            // set up shift to isolate the highest nibble
    if(!w || w > max_strhex)                        // no bold params
        return p;                                   // do nothing for the rebel
    mask  = mask >> (max_strhex-w)*4;               // setup mask to extract hex nibbles
    for(i = 0; i < w; i++){                         // loop and add w nibbles
        shift = shift - 4;                          // hint: start mask for four bit hex is 0xF000, shift is 32, mask >> 32 is 0x0000, mask >> 28 is 0x000F.
        *p++ = TO_HEX(((n & mask) >> shift));       // isolate digit and make hex
        mask = mask >> 4;                           //
        *p = '\0';                                  // be nice to silly people
    }                                               //
    return p;                                       // point to null, allow concatenation
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接