Преобразование int в 2-байтовое шестнадцатеричное значение в C

18

Мне нужно преобразовать int в 2-байтовое шестнадцатеричное значение для хранения в массиве char, в C. Как я могу это сделать?

    
задан MBU 03.11.2010 в 10:24
источник
  • тип данных int 32-бит, а шестибайтовое значение 2 байта - 8 бит. Если ваш int> 255, он не будет соответствовать вашему шестнадцатеричному значению (он будет переполняться). Вы имеете в виду подпись / unsigned char вместо int? –  invert 03.11.2010 в 10:32
  • @wez: int не обязательно 32 бит. Но ваш вопрос хороший, ему нужно следить за переполнением. –  Vicky 03.11.2010 в 10:39
  • Этот вопрос выглядит как домашнее задание ... Это правда? Если да, добавьте тег «домашняя работа». –  Denilson Sá Maia 03.11.2010 в 11:45
  • @ Denilson: «Домашний тег, как и другие так называемые мета-теги, теперь обескуражен», но, @MikeU, пожалуйста (как всегда) следуйте общим рекомендациям, укажите любые специальные ограничения, покажите, что у вас есть попробовал до сих пор, и спросите, что конкретно вас путает. –  general guidelines 08.11.2010 в 21:56

15 ответов

31

Если вам разрешено использовать библиотечные функции:

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

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

Ваше целое число может содержать более четырех шестнадцатиричных значений, поэтому сначала проверьте.

Если вам не разрешено использовать библиотечные функции, разделите его на nybbles вручную:

#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] = '%pr_e%';
}
    
ответ дан Vicky 03.11.2010 в 10:38
  • Из просмотра ответов других людей кажется, что они интерпретируют «двухбайтное шестнадцатеричное значение», что означает два nybbles, каждый из которых представлен одним байтовым шестнадцатеричным символом. Я воспринял это как два байта данных, каждый из которых представлен двумя шестнадцатеричными символами. Вы должны уточнить, что вы имеете в виду! –  Vicky 03.11.2010 в 10:40
  • Спасибо за ответ @Vicky. Используется для построения функции в ответе ниже. –  10SecTom 08.11.2017 в 10:36
4

Предполагая, что int будет 32 бита,

Самый простой способ: просто используйте sprintf ()

int intval = /*your value*/
char hexval[5];
sprintf(hexval,"%0x",intval);

Теперь используйте hexval [0] через hexval [3]; если вы хотите использовать его как строку с нулевым завершением, добавьте hexval[4]=0;

    
ответ дан slashmais 03.11.2010 в 10:36
  • При 0xFF <intval вы получите непредсказуемые результаты (даже сбой). –  Vovanium 03.11.2010 в 11:16
  • Нет. Поскольку sprintf форматирует intval в строку. Таким образом, 0xFFFF (который не является максимальным значением для 32-битного целого числа кстати) будет четыре F, и они не будут вписываться в hexval [3], так как вам также нужно учитывать конечный 0. Вам не придется добавлять hexval [2] = 0 кстати. –  lx. 03.11.2010 в 15:34
  • хорошо, только платя половину ума - вы правы - исправлено это –  slashmais 03.11.2010 в 16:08
3
char s[5];  // 4 chars + '%pr_e%'
int x = 4660;
sprintf(s, "%04X", x);

Вероятно, вы захотите проверить документацию sprintf() . Будьте осторожны, чтобы этот код был не очень безопасным. Если x больше 0xFFFF , окончательная строка будет содержать более 4 символов и не будет соответствовать. Чтобы сделать его более безопасным, просмотрите snprintf() .

    
ответ дан Denilson Sá Maia 03.11.2010 в 10:33
  • , если int равно 11. Мне нужно, чтобы в результате получилось 2 байта, равное 0 B, которое равно 11 в шестнадцатеричном формате. –  MBU 03.11.2010 в 11:29
  • Неправильно, эти два символа являются полубайтами, также называемыми nibbles. Байт (8 бит, 0-255) состоит из 2 шестнадцатеричных символов. Таким образом, 2 байта состоят из 4 шестнадцатеричных символов. Каждый шестнадцатеричный символ (или полубайт) имеет 4 бита (0-15 или 0-F). –  Denilson Sá Maia 03.11.2010 в 11:43
2

Обычно я рекомендую использовать решения на основе sprintf , рекомендованные другими. Но когда я написал инструмент, который должен был преобразовать миллиарды элементов в hex, sprintf был слишком медленным. Для этого приложения я использовал массив элементов 256, который отображает байты в строки.

Это неполное решение для преобразования 1 байта, не забудьте добавить проверку границ и убедиться, что массив статичен или глобальный, воссоздание его для каждой проверки приведет к снижению производительности.

static const char hexvals[][3]= {"00", "01", "02", ... "FD", "FE", "FF"};
const char *byteStr = hexvals[number];
    
ответ дан mikerobi 03.11.2010 в 16:31
2

Выяснилось, что я проверил, и он работает.

int value = 11;

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

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

результат:

000B

, который равен 11 в шестнадцатеричном формате.

    
ответ дан MBU 04.11.2010 в 08:37
1

Вместо sprintf , я бы рекомендовал вместо этого использовать snprintf .

#include <stdio.h>

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

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

Это намного безопаснее и доступно почти в каждом компиляторе.

    
ответ дан MAK 03.11.2010 в 10:44
1
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);
....
    
ответ дан cooxee 09.11.2015 в 20:57
  • Помогите объяснить свой ответ, чтобы люди могли учиться на нем? –  Machavity 09.11.2015 в 21:13
0

Большинство из этих ответов велики, есть только одна вещь, которую я бы добавил: вы можете использовать sizeof для безопасного резервирования правильного количества байтов. Каждый байт может принимать до двух шестнадцатеричных цифр (255 - > ff), поэтому это два символа на каждый байт. В этом примере я добавляю два символа для префикса «0x» и один символ для конечного NUL.

int bar; 
// ...
char foo[sizeof(bar) * 2 + 3];
sprintf(foo, "0x%x", bar);
    
ответ дан Joe Valenzuela 03.11.2010 в 15:36
0
unsigned int hex16 = ((unsigned int) input_int) & 0xFFFF;

input_int - это номер, который вы хотите преобразовать. hex16 будет иметь наименее значимые 2 байта input_int . Если вы хотите распечатать его на консоли, используйте %x в качестве спецификатора формата вместо %d , и он будет напечатан в шестнадцатеричном формате.

    
ответ дан yasouser 03.11.2010 в 16:15
0

Вот грубый способ сделать это. Если мы не можем верить, что кодировка значений ascii будет последовательной, мы просто создаем сопоставление шестнадцатеричных значений в char. Вероятно, его можно оптимизировать, подобрать и сделать красивее. Также предполагается, что мы только смотрим на захват последних 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] = '%pr_e%'; // null terminate it

  printf("buf: %s\n", buf);
  return 0;
}
    
ответ дан jbremnant 03.11.2010 в 17:33
  • 32 бит / 4 бит на шестнадцатеричный символ = 8 символов. Не 4. –  Chris S 18.04.2012 в 17:37
0

Эта функция работает как шарм.

void WORD2WBYTE(BYTE WBYTE[2], WORD Value) { 
    BYTE tmpByte[2]; 
    // Converts a value from word to word byte ----
    memcpy(tmpByte, (BYTE*) & Value, 2); 
    WBYTE[1] = tmpByte[0]; 
    WBYTE[0] = tmpByte[1]; 
} 

запустив следующее:

typedef unsigned char   BYTE; 
typedef unsigned short  WORD;

Пример использования:

мы хотим достичь этого:

integer = 92
byte array in hex:
a[0] = 0x00;
a[1] = 0x5c;

unsigned char _byteHex[2];
WORD2WBYTE(_byteHex, 92);
    
ответ дан Carlos E Mejia Martinez 06.06.2014 в 06:30
0

вы можете использовать это, это просто и легко конвертировать

typedef union {
    struct hex{
            unsigned  char a;
            unsigned  char b;

    }hex_da;
    short int dec_val;
}hex2dec;

hex2dec value;
value.dec_val=10;

Теперь шестнадцатеричное значение сохраняется в структуре hex_da для его дальнейшего использования.

    
ответ дан manikanta 22.04.2017 в 14:12
0

Использование ответа Вики выше

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 = '%pr_e%';                                  // be nice to silly people
    }                                               //
    return p;                                       // point to null, allow concatenation
}
    
ответ дан 10SecTom 08.11.2017 в 10:40
0

Для динамической фиксированной длины hex

string makeFixedLengthHex(const int i, const int length)
{
    std::ostringstream ostr;
    std::stringstream stream;
    stream << std::hex << i;
    ostr << std::setfill('0') << std::setw(length) << stream.str();
    return ostr.str();
}

Но отрицательно вы должны справиться с этим сами.     

ответ дан Md. Yusuf 28.01.2018 в 07:14
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);
}
    
ответ дан Alexander Rafferty 03.11.2010 в 10:35
  • Этот код предполагает, что буквы от A до F занимают последовательные кодовые точки. Это не гарантируется языком C. –  Bart van Ingen Schenau 03.11.2010 в 10:56
  • Можете ли вы представить себе какую-либо реализацию или кодировку, которая не имеет букв подряд? –  Alexander Rafferty 03.11.2010 в 11:02
  • Код Бодо, код СССР «УПП» (Код-УПП). –  Vovanium 03.11.2010 в 11:29
  • Все еще хороший ответ, возможно, должен включать в себя код Бодо и код-UPP. –  Gewure 02.02.2017 в 13:34