Преобразование 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

856   10  
c

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));
}
int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*

зачем вам нужно промежуточное приведение к 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

    Ничего не найдено.