Подтвердить что ты не робот

Преобразование int в массив размером 4 байта char (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

4b9b3361

Ответ 1

Портативный способ сделать это (гарантируя, что вы получите 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).

-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]);

Ответ 2

Вы хотите обратиться к отдельным байтам 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 для отражения значений без знака.

Ответ 3

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

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

Функция htonl() принимает в качестве аргумента 32-разрядное целое без знака (в отличие от htons(), которое принимает беззнаковое 16-разрядное целое) и преобразует его в сетевой порядок байтов из порядка байтов хоста (отсюда и сокращение, Host TO Network Long, против Host TO Network Short для htons), возвращая результат как 32-битное целое без знака. Цель этого семейства функций - обеспечить, чтобы все сетевые коммуникации выполнялись в порядке большого байта байтов, чтобы все машины могли взаимодействовать друг с другом через сокет без проблем с порядком байтов. (В стороне, для машин большого конца, функции htonl(), htons(), ntohl() и ntohs() обычно скомпилированы, чтобы просто быть "no 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, которая использует малое порядковое число байтов), который является шестнадцатеричным для 175.

Ответ 4

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

void CopyInt(int value, char* buffer) {
  memcpy(buffer, (void*)value, sizeof(int));
}

Ответ 5

int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*

Ответ 6

Зачем вам нужен промежуточный листинг в void * в С++ Поскольку cpp не допускает прямого преобразования между указателями, вам нужно использовать reinterpret_cast или casting для void * делает вещь.

Ответ 7

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

Ответ 8

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);
    

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

Ответ 9

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

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

Ответ 10

Я думаю, что это самое простое и более эффективное решение:

unsigned char bytes[4];
unsigned int number = 123456;

*(unsigned int*)bytes = number

Ответ 11

Проблема возникает, поскольку 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]);