Преобразование int в 4-байтовый массив символов (C)
Эй, я хочу преобразовать int, который вводится пользователем в 4 байта, который я присваиваю массиву символов. Как это может быть сделано?
Пример:
Преобразуйте пользовательские входы от 175 до
- C: Приведение минимального 32-битного целого числа (-2147483648) к float дает положительное число (2147483648.0)
- C - инициализация указателей, позиция звездочки
- Является ли пустой список инициализаций допустимым кодом C?
- Как указатель на указатели работает в C?
- Многомерные многомерные массивы C / C ++
00000000 00000000 00000000 10101111
Проблема со всеми ответами до сих пор, преобразование 255 должно приводить к 0 0 0 ff
хотя оно 0 0 0 ffffffff
как: 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, ffffffaf
когда он должен быть только 0, 0, 0, af
- Разница в int8_t, int_least8_t и int_fast8_t?
- Как включить / выключить флэш-память iPhone?
- Что случилось с этим кодом C 1988 года?
- Что означает ... означает в списке аргументов в C?
- Почему getchar () не распознает return как EOF на консоли?
- Является ли модификация строковых литералов неопределенным поведением в соответствии со стандартом C89?
- undefined символ для архитектуры x86_64 при компиляции программы C
- Правильный способ утилиты Image / Bitmap и PictureBox
Портативный способ сделать это (гарантируя, что вы получаете 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;
Методы, использующие union и 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
на 0xff
с добавлением 2s).
-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
, который представляет собой большой байтовый порядок байтов, также известный как порядок сетевых байтов .
В основном переносимый способ преобразования вашего беззнакового целого в массив символов без знака без знака, как вы предположили из этого примера «175», который вы htonl()
, будет использовать htonl()
C htonl()
C (определенную в заголовке
на системах Linux), чтобы преобразовать ваш unsigned int в байтовый порядок байтов, затем используйте memcpy()
(определенный в заголовке
для C,
для C ++), чтобы скопировать байты в ваш char (или unsigned char ).
Функция htonl()
принимает в качестве аргумента неподписанное 32-битное целое число (в отличие от htons()
, которое принимает целое число без знака 16 бит) и преобразует его в сетевой порядок байтов из порядка байтов хоста (следовательно, аббревиатура , Host TO Network Long, против Host TO Network Short для htons
), возвращая результат как 32-битное целое без знака. objective этого семейства функций – обеспечить, чтобы все сетевые коммуникации выполнялись в порядке большого байта байтов, чтобы все машины могли взаимодействовать друг с другом через сокет без проблем с порядком байтов. (В стороне, для машин htonl()
, функции htonl()
, htons()
, ntohl()
и ntohs()
обычно скомпилированы, чтобы просто быть «no op», потому что байты не нужно переворачивать прежде чем они будут отправлены или получены из сокета, поскольку они уже находятся в правильном порядке байтов)
Вот код:
#include #include #include 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; }
Обратите внимание, что, как сказал кафе, вам нужно напечатать символы как символы без знака, используя спецификатор формата %x
printf.
Вышеприведенный код печатает 0 0 0 af
на моей машине (машина x86_64, в которой используется малое порядковое число байтов), который является шестнадцатеричным для 175.
Можешь попробовать:
void CopyInt(int value, char* buffer) { memcpy(buffer, (void*)value, sizeof(int)); }
int a = 1; char * c = (char*)(&a); //In C++ should be intermediate cst to void*
Зачем вам нужен промежуточный листинг для void * в C ++. Поскольку cpp не разрешает прямое преобразование между указателями, вам нужно использовать reinterpret_cast или casting для void * делает вещь.
Проблема с преобразованием (причина, по которой он дает вам ffffff в конце), состоит в том, что ваше шестнадцатеричное целое (с которым вы используете & с двоичным оператором) интерпретируется как подписанное. Внесите его в целое число без знака, и все будет в порядке.
uint8_t
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);
Надеюсь, поможет.
Проблема возникает, поскольку 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]);
Я не буду писать код. Просто объявите int-указатель и назначьте ему адрес массива. Затем скажите, что все, что находится в этом месте указателя, равно целому числу, которое вы хотите преобразовать. Компилятор заботится обо всем остальном …