Преобразование 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
10 ответов:
The портативный способ сделать это (гарантируя, что вы получите
0x00 0x00 0x00 0xafвезде) - использовать сдвиги:unsigned char bytes[4]; 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на машине 2S-complement).-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]);
вы хотите обратиться к отдельным байтам 32-разрядного int? Одним из возможных методов является объединение:
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, чтобы отразить беззнаковые значения.
в своем вопросе вы заявили, что хотите преобразовать пользовательский ввод 175 в
00000000 00000000 00000000 10101111, которая составляет big endian порядок байтов, также известный как сетевой порядок байт.A в основном портативный способ преобразовать ваше целое число без знака в большой массив символов без знака endian, как вы предположили из этого примера "175", который вы дали, будет использовать C
htonl()функция (определяется в заголовке<arpa/inet.h>в системах Linux) для преобразования вашего unsigned инт с прямым порядком байтов, а затем использоватьmemcpy()(определенных в заголовке<string.h>для C,<cstring>для C++), чтобы скопировать байты в массив char (или unsigned char).The
htonl()функция принимает в качестве аргумента 32-разрядное целое число без знака (в отличие отhtons(), который принимает беззнаковое 16-разрядное целое число) и преобразует его в порядок байтов сети из порядка байтов хоста (отсюда аббревиатура, Хост в Сеть долго, против Хоста в Сеть коротко дляhtons), возвращает результат в виде 32-разрядного целого числа без знака. Цель этого семейства функций состоит в том, чтобы гарантировать, что все сетевые коммуникации происходят в большом порядке байтов endian, так что все машины могут общаться друг с другом через сокет без проблем порядка байтов. (Как в стороне, на тупоконечников машины,htonl(),htons(),ntohl()иntohs()функции обычно компилируются так, чтобы быть просто "без op", потому что байты не нужно переворачивать, прежде чем они будут отправлены или получены от сокет, так как они уже находятся в правильном порядке байтов)вот код:
#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
%xформат описателя.приведенный выше код печатает
0 0 0 afна моей машине (машина x86_64, которая использует небольшой порядок байтов endian), который является шестнадцатеричным для 175.
можно попробовать:
void CopyInt(int value, char* buffer) { memcpy(buffer, (void*)value, sizeof(int)); }
зачем вам нужно промежуточное приведение к void * в C++ Поскольку cpp не позволяет прямое преобразование между указателями,вам нужно использовать reinterpret_cast или приведение к void* делает это.
проблема с преобразованием (причина, по которой он дает вам ffffff в конце) заключается в том, что ваше шестнадцатеричное целое число (с которым вы используете оператор & binary) интерпретируется как подписанное. Приведите его к целому числу без знака, и все будет в порядке.
An
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);надеюсь, что это помогает.
проблема возникает, поскольку беззнаковый символ - это 4-байтовое число, а не 1-байтовое число, как многие думают, поэтому измените его на
union { unsigned int integer; char byte[4]; } temp32bitint;и литой во время печати, чтобы предотвратить продвижение к 'int' (который C делает по умолчанию)
printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);
Я не собираюсь писать никакой код. Просто объявите указатель int и назначьте ему адрес массива символов. Затем скажите, что все, что находится в этом месте указателя, равно целому числу, которое вы хотите преобразовать. Компилятор заботится обо всем остальном...
Comments