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

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

Пример:

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

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

Портативный способ сделать это (гарантируя, что вы получаете 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-указатель и назначьте ему адрес массива. Затем скажите, что все, что находится в этом месте указателя, равно целому числу, которое вы хотите преобразовать. Компилятор заботится обо всем остальном …

  • Разница между объявленной строкой и выделенной строкой
  • Оценка короткого замыкания и побочные эффекты
  • Что такое блок C # Using и почему я должен его использовать?
  • Суффикс «f» по плавающей стоимости?
  • Gcc автоматически инициализирует статические переменные до нуля?
  • Как «while (* s ++ = * t ++)» скопировать строку?
  • Программа не останавливается на строке scanf («% c», & ch), почему?
  • C - О чем этот синтаксис? <<
  • Как я могу написать общий class контейнера, который реализует данный интерфейс в C #?
  • В C, почему несколько деклараций работают нормально для глобальной переменной, но не для локальной переменной?
  • Что означает void * и как его использовать?
  • Interesting Posts
    Давайте будем гением компьютера.