Мусор, появляющийся при конвертации в char из int32 в C / C ++ - PullRequest
0 голосов
/ 29 ноября 2018

Я использую простой код для преобразования переменной uint32_t в char.

uint32_t len = 4 + data.length(); //data is a string
char pop1 = len & 0xff;
char pop2 = (len >> 8) & 0xff;
char pop3 = (len >> 16) & 0xff;
char pop4 = (len >> 24) & 0xff;     //also tried the same thing with memcpy

printf("%02x \n",pop1);
printf("%02x \n",pop2);
printf("%02x \n",pop3);
printf("%02x \n",pop4); 

Вывод:

ffffff81
02
00
00

Я не понимаю, почему мусор добавляется к первому байту.Когда я использую unsigned char вместо этого, мусор не добавляется.В моем понимании как char, так и unsigned char являются 8-битными, тогда почему char обрабатывается как 32-битное значение.Я использую VS2015 на 64-битной машине Windows.Я хочу использовать массив символов для функции отправки WinSock2.

send(ConnectSocket, sendbuf, size_to_send, 0); // sendbuf is a char array

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Когда значение типа малого целого (например, char) передается в качестве аргумента функции vararg (например, printf), оно повышается до int

Эта акция может включать расширение знака , если малый тип - signed.

На системах, дополняющих два (что является обширнымбольшинство компьютеров долгое время), что означает, что int будет дополнен 1 битами, что при печати в виде unsigned int в шестнадцатеричном виде будет проявляться как f.

Простое решение заключается вне используйте char, но желательно uint8_t или явный тип unsigned char для ваших переменных.

0 голосов
/ 29 ноября 2018

Подумайте обо всех изменениях типов и происходящих конверсиях.Их как минимум 4.

0xff, int преобразуется в uint32_t, затем происходит &.Здесь нет проблем.

len & 0xff;

Затем этот результат присваивается char, со знаком char в случае OP.Это присваивает 0x81 (129), выходящий за пределы диапазона char -> Определенное реализацией поведение .Общий результат просто передает наименьшие биты.

char pop1 = len & 0xff;

, почему символ обрабатывается как 32-битное значение (?)

Он еще не обрабатывается как32-разрядное значение без знака , но в виде 8-разрядного значения со знаком .

Затем код передается char pop1 (возможно со значением -127) вprintf(); и включает продвижение аргумента по умолчанию в качестве аргумента функции ....printf() получает int со значением -127.

printf(...,pop1);

printf("%02x \n",pop1); ожидает unsigned, а не int.Поскольку значение -127 не может быть представлено как int и unsigned, (c11 §6.5.2.2 6), спецификатор преобразования недопустим с этим аргументом, и в результате получается неопределенное поведение (УБ).(§7.21.6.1 9).Обычно происходит то, что битовая комбинация -127, переданная как int, интерпретируется как битовая комбинация для unsigned и приводит к "ffffff81".

printf("%02x \n",pop1);

Во избежаниеРеализация определенного поведения и UB, рекомендую ниже.Для эффективного кода без знака четко используйте типы без знака , объекты и константы.

unsigned char pop1 = len & 0xffu;
// or
uint8_t pop1 = len & 0xffu;
0 голосов
/ 29 ноября 2018

При использовании в выражении char сначала повышается до int.Таким образом, если значение char является отрицательным, это значение сохраняется при преобразовании в int, и это то, что вы видите при печати. ​​

Вы можете либо привести значение к unsigned char, чтобы оно приняло положительное значение, или вы можете использовать модификатор hh в спецификаторе формата %x, чтобы оно обрабатывало значение как unsigned char.

printf("%02hhx \n",pop1);
printf("%02hhx \n",pop2);
printf("%02hhx \n",pop3);
printf("%02hhx \n",pop4);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...