копирование короткого int в массив символов

У меня есть короткая целочисленная переменная с именем s_int, которая содержит значение = 2.

unsighed short s_int = 2;

Я хочу скопировать этот номер в массив символов в первую и вторую позицию массива символов.

Допустим, у нас есть char buffer[10];. Мы хотим, чтобы два байта s_int были скопированы в buffer[0] и buffer[1].

Как мне это сделать?


person cateof    schedule 01.06.2010    source источник


Ответы (5)


Обычный способ сделать это — использовать побитовые операторы для нарезки и нарезки, побайт за раз:

b[0] = si & 0xff;
b[1] = (si >> 8) & 0xff;

хотя на самом деле это должно быть сделано в unsigned char, а не в простом char, поскольку они подписаны в большинстве систем.

Сохранение больших целых чисел можно сделать аналогичным образом или с помощью цикла.

person crazyscot    schedule 01.06.2010
comment
в чем причина & 0xff? - person Almir; 11.12.2013
comment
Он превращает неявное усечение в явное. Другими словами, намерение программиста становится ясным. (Думаю, некоторые компиляторы могут пожаловаться на это?) - person crazyscot; 12.12.2013
comment
о, я понял :) спасибо - person Almir; 12.12.2013
comment
Как восстановить int из b[0] и b[1]? - person Casey; 15.10.2020

*((short*)buffer) = s_int;

Но viator emptor, результирующий порядок байтов будет меняться в зависимости от порядка следования байтов.

person James    schedule 01.06.2010
comment
gcc может сказать вам, use of cast expressions as lvalues is deprecated. - person John Ledbetter; 02.06.2010
comment
человек, никак - подумайте о раскладе. Если буфер указывает на нечетный индекс в памяти - допустим, предположим адрес 0xFFF01, что у вас большие проблемы. - person INS; 02.06.2010
comment
@Iulian: я не слышал об этом ограничении для x86, но, конечно, оно имеет фундаментальное значение для некоторых других архитектур. - person crazyscot; 02.06.2010
comment
@Iulian: это не проблема для X86 (хотя, возможно, только по скорости ...). Однако это важно на других платформах, таких как IA64, MIPS, возможно, ARM и так далее. - person botismarius; 02.06.2010
comment
@crazyscot и @botismarius Я согласен с вашими замечаниями, но мы имеем в виду C; мы должны стараться быть максимально портативными. - person INS; 02.06.2010
comment
Действительно, предупреждение об устаревании, о котором я упоминал, я видел на платформе msp430, где выравнивание памяти является проблемой. Мне не удалось сгенерировать это предупреждение на моем блоке amd64. - person John Ledbetter; 02.06.2010
comment
Джон Ледбеттер: В этом коде выражение приведения не используется в качестве lvalue; он использует результат унарного оператора * в качестве lvalue, и это нормально (потому что это является lvalue). Однако у него все еще есть проблема с выравниванием. (Использование приведения в качестве lvalue — это выражение типа (int)x = 10;) - person caf; 02.06.2010

С помощью указателей и приведения типов.

unsigned short s_int = 2;
unsigned char buffer[sizeof(unsigned short)];

// 1.
unsigned char * p_int = (unsigned char *)&s_int;
buffer[0] = p_int[0];
buffer[1] = p_int[1];

// 2.
memcpy(buffer, (unsigned char *)&s_int, sizeof(unsigned short));

// 3.
std::copy((unsigned char *)&s_int,
          ((unsigned char *)&s_int) + sizeof(unsigned short),
          buffer);

// 4.
unsigned short * p_buffer = (unsigned short *)(buffer); // May have alignment issues
*p_buffer = s_int;

// 5.
union Not_To_Use
{
  unsigned short s_int;
  unsigned char  buffer[2];
};

union Not_To_Use converter;
converter.s_int = s_int;
buffer[0] = converter.buffer[0];
buffer[1] = converter.buffer[1];
person Thomas Matthews    schedule 01.06.2010

Я бы запомнил это, что-то вроде

memcpy(buffer, &s_int, 2);

Порядок следования байтов сохраняется правильно, поэтому, если вы приведете буфер к беззнаковому короткому *, вы сможете правильно прочитать то же значение s_int. Другое решение должно поддерживать порядок байтов, иначе вы можете поменять местами lsb и msb. И, конечно же, sizeof(short) должен быть равен 2.

person ShinTakezou    schedule 01.06.2010
comment
memcpy() — хороший подход, но обратите внимание, что сохранение порядка следования байтов не всегда правильно. Ответ Crazyscot помещает ответ в буфер с известным порядком байтов, что часто действительно необходимо (например, если буфер нужно сохранить в файл или отправить по сети). Ваш ответ помещает ответ в буфер с порядком байтов host, что также иногда необходимо (но реже). - person caf; 02.06.2010
comment
да, конечно: с порядком байтов сохраняется Я хотел сказать, что данные хранятся в буфере так же, как короткое хранится в памяти, что позволяет получить прямой доступ к короткому значению из буфера в, при условии, что пользователю не нужно изменять endianness во что-то конкретное. - person ShinTakezou; 02.06.2010
comment
Однако обратите внимание, что прямой доступ к шорту из буфера возможен только в том случае, если буфер правильно выровнен для такого доступа; в общем, если вы собираетесь напрямую обращаться к нему как к короткому, вы должны были объявить его как struct, содержащий член short, а не как массив char. - person caf; 03.06.2010
comment
на процессоре, которому требуется выравнивание, и на процессоре, которому необходимо выравнивание по 2 байтам, буфер тоже выравнивается, поэтому к нему можно получить доступ; x86, насколько я знаю, этого не требует (наверное, доступ к невыровненной памяти только медленнее). - person ShinTakezou; 03.06.2010

Если вы не хотите делать все эти побитовые вещи, вы можете сделать следующее

char* where = (char*)malloc(10);
short int a = 25232;
where[0] = *((char*)(&a) + 0);
where[1] = *((char*)(&a) + 1);
person M. Williams    schedule 01.06.2010