Преобразование int в 4-байтовый массив символов (C)

Эй, я хочу преобразовать int, который вводится пользователем, в 4 байта, которые я назначаю массиву символов. Как это может быть сделано?

Пример:

Преобразовать пользовательский ввод 175 в

00000000 00000000 00000000 10101111

Вопрос со всеми ответами до сих пор, преобразование 255 должно привести к0 0 0 ff хотя распечатывается как:0 0 0 ffffffff

unsigned int value = 255;   

buffer[0] = (value >> 24) & 0xFF;
buffer[1] = (value >> 16) & 0xFF;
buffer[2] = (value >> 8) & 0xFF;
buffer[3] = value & 0xFF;

union {
    unsigned int integer;
    unsigned char byte[4];
} temp32bitint;

temp32bitint.integer = value;
buffer[8] = temp32bitint.byte[3];
buffer[9] = temp32bitint.byte[2];
buffer[10] = temp32bitint.byte[1];
buffer[11] = temp32bitint.byte[0];

оба результата в0 0 0 ffffffff вместо0 0 0 ff

Просто еще один пример - 175, поскольку входные данные распечатываются как0, 0, 0, ffffffaf когда это должно быть просто0, 0, 0, af

 pmg24 сент. 2010 г., 10:33
Nit: у вас нет гарантии, что 4 байта необходимы и достаточны для хранения int. Тебе нужноsizeof (int) байт.
 caf24 сент. 2010 г., 08:40
..но обратите внимание, что%hhx это дополнение C99.
 Jens Gustedt24 сент. 2010 г., 08:22
Вы должны использовать формат% hhx для печати ваших чисел.
 Blastfurnace24 сент. 2010 г., 08:16
Как определяется ваш буфер []? Байт без знака со значением больше 127 имеет старший значащий бит. Это означает отрицательное число при использовании подписанного байта. Ваш FFFFFFFF выглядит как расширенная интерпретация байта 0xFF.
 Lundin13 мар. 2019 г., 14:53
Для тех, кто может столкнуться с этим постом: единственное правильное решение - использовать битовое смещение для типов без знака, как в принятом ответе. Вы можете прочитать это и остановиться там. Это самая быстрая и самая портативная версия.memcpy для беззнаковых типов это нормально, если все типы без знака и учитывается порядок байтов. Объединенные решения не подходят, они непереносимы - зачем писать непереносимый код, если вы можете получить переносимый код с такими же усилиями? Арифметические решения с указателями не подходят, они могут быть медленными, определенно непереносимыми и часто вызывают плохо определенное поведение.

Ответы на вопрос(10)

int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*
 AnT24 сент. 2010 г., 06:56
Зачем вам нужен промежуточный составvoid * в С ++?
Решение Вопроса

портативный способ сделать это (гарантируя, что вы получите0x00 0x00 0x00 0xaf везде) это использовать смены:

unsigned long n = 175;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;

Методы, использующие союзы иmemcpy() получит другой результат на разных машинах.

Проблема, с которой вы столкнулись, связана с печатью, а не с конверсией. Я полагаю, вы используетеchar скорее, чемunsigned charи вы используете такую ​​строку, чтобы напечатать ее:

printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);

Когда какие-либо типы уже, чемint передаютсяprintf, они повышены доint (или жеunsigned int, еслиint не может содержать все значения исходного типа). Еслиchar подписан на вашей платформе, то0xff скорее всего, не вписывается в диапазон этого типа, и вместо этого устанавливается -1 (который имеет представление0xff на 2-х машинке).

-1 повышен доintи имеет представление0xffffffff какint на вашей машине, и это то, что вы видите.

Ваше решение - либо использоватьunsigned charили же приведен кunsigned char вprintf заявление:

printf("%x %x %x %x\n", (unsigned char)bytes[0],
                        (unsigned char)bytes[1],
                        (unsigned char)bytes[2],
                        (unsigned char)bytes[3]);
 ZerOne06 сент. 2016 г., 11:00
Не могли бы вы объяснить '& 0xFF;' немного пожалуйста? Что делает этот код?
 Jacob Nelson24 сент. 2010 г., 07:57
Отредактировал мой вопрос, чтобы вы могли увидеть проблему, с которой вы столкнулись, в вашем решении.
 caf24 сент. 2010 г., 08:14
@jacobnlsn: Это проблема с тем, как вы ее печатаете, смотрите обновление.
 caf17 окт. 2017 г., 07:34
@rem: Хотя редко,char разрешено быть шире, чем 8 бит (некоторые среды программирования DSP демонстрируют это), поэтому маска просто гарантирует, что в этом случае происходит правильно. Для обычного случая он все равно будет оптимизирован.
 caf06 сент. 2016 г., 13:56
Zerone:& является побитовым И, который дает результат, где каждый бит равен 1, если соответствующие биты в обоих операндах равны 1.a & 0xFF затем дает результат, где младшие 8 битов совпадают с младшими 8 битами вaи все остальные биты равны нулю.
 rem17 окт. 2017 г., 00:11
В этом случае полезно ли применять маску 0xFF? Преобразование длинных без знака в беззнаковый символ сохраняет только самый правый байт

не позволяет прямое преобразование между указателями, вам нужно использовать reinterpret_cast или приведение к void *.

Ты можешь попробовать:

void CopyInt(int value, char* buffer) {
  memcpy(buffer, (void*)value, sizeof(int));
}
 Lundin13 мар. 2019 г., 14:46
Вы не должны использоватьchar для байтов используйтеuint8_t. (void*)value просто неправильно, должно быть&value.

int эквивалентноuint32_t а такжеchar вuint8_t.

Я покажу, как я разрешил взаимодействие клиент-сервер, отправив фактическое время (4 байта, отформатированное в эпоху Unix) в 1-битный массив, а затем перестроил его на другой стороне. (Примечание: протокол должен был отправить 1024 байта)

Сторона клиента

uint8_t message[1024];
uint32_t t = time(NULL);

uint8_t watch[4] = { t & 255, (t >> 8) & 255, (t >> 16) & 255, (t >> 
24) & 255 };

message[0] = watch[0];
message[1] = watch[1];
message[2] = watch[2];
message[3] = watch[3];
send(socket, message, 1024, 0);

Серверная сторона

uint8_t res[1024];
uint32_t date;

recv(socket, res, 1024, 0);

date = res[0] + (res[1] << 8) + (res[2] << 16) + (res[3] << 24);

printf("Received message from client %d sent at %d\n", socket, date);

Надеюсь, поможет.

что хотите преобразовать пользовательский ввод 175 в00000000 00000000 00000000 10101111, которыйBig Endian порядок байтов, также известный каксетевой порядок байтов.

A в основном Переносимый способ преобразования вашего целого без знака в массив символов без знака с прямым порядком байтов, как вы предложили из приведенного вами примера "175", заключался бы в использовании Сиhtonl() функция (определена в заголовке<arpa/inet.h> в системах Linux) для преобразования вашего unsigned int в порядок байтов с прямым порядком байтов, затем используйтеmemcpy() (определено в заголовке<string.h> для С,<cstring> для C ++) скопировать байты в ваш массив char (или unsigned char).

htonl() функция принимает в качестве аргумента 32-разрядное целое число без знака (в отличие отhtons(), который принимает беззнаковое 16-битное целое число) и преобразует его в сетевой порядок байтов из порядка байтов хоста (отсюда и сокращение «хост-сеть длинная» по сравнению с хостом-сеть короткая дляhtons), возвращая результат в виде 32-разрядного целого числа без знака. Целью этого семейства функций является обеспечение того, чтобы все сетевые соединения происходили в порядке байтов с прямым порядком байтов, чтобы все машины могли взаимодействовать друг с другом через сокет без проблем с порядком байтов. (Как в стороне, для машин с прямым порядком байтов,htonl(), htons(), ntohl() а такжеntohs() функции, как правило, компилируются так, чтобы они были просто «без операции», потому что байты не нужно переворачивать, прежде чем они будут отправлены или получены из сокета, поскольку они уже находятся в правильном порядке байтов)

Вот код:

#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>

int main() {
    unsigned int number = 175;

    unsigned int number2 = htonl(number);
    char numberStr[4];
    memcpy(numberStr, &number2, 4);

    printf("%x %x %x %x\n", numberStr[0], numberStr[1], numberStr[2], numberStr[3]);

    return 0;
}

Обратите внимание, что, как сказал caf, вы должны напечатать символы какнеподписанный символы, использующие printf's%x спецификатор формата.

Выше код распечатывает0 0 0 af на моей машине (машина x86_64, которая использует порядок байтов с прямым порядком байтов), что является шестнадцатеричным для 175.

по которой он дает вам ffffff в конце) заключается в том, что ваше шестнадцатеричное целое число (с которым вы используете & двоичный оператор) интерпретируется как подписанное. Приведите его к целому числу без знака, и все будет в порядке.

поскольку unsigned char - это 4-байтовое число, а не 1-байтовое число, как многие думают, поэтому измените его на

union {
unsigned int integer;
char byte[4];
} temp32bitint;

и приведение во время печати, чтобы предотвратить повышение до 'int' (что C делает по умолчанию)

printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);

Вы можете просто использоватьmemcpy следующее:

unsigned int value = 255;
char bytes[4] = {0, 0, 0, 0};
memcpy(bytes, &value, 4);

жных методов является объединение:

union
{
    unsigned int integer;
    unsigned char byte[4];
} foo;

int main()
{
    foo.integer = 123456789;
    printf("%u %u %u %u\n", foo.byte[3], foo.byte[2], foo.byte[1], foo.byte[0]);
}

Примечание: исправлен printf для отображения значений без знака.

 Tadeusz A. Kadłubowski24 сент. 2010 г., 08:16
Я бы написал uint32_t вместо int, чтобы не беспокоиться о 32-х и 64-х битных машинах.
 Jacob Nelson24 сент. 2010 г., 07:58
Отредактировал мой вопрос, чтобы вы могли увидеть проблему, с которой вы столкнулись, в вашем решении.
 bzeaman04 нояб. 2014 г., 10:48
Будьте осторожны, чтобы убедиться, что вы не имеете дело с неопределенным поведением.stackoverflow.com/questions/11639947

Ваш ответ на вопрос