Алгоритм для записи целого числа дополнения двух в память переносимо
Скажем, у меня есть следующее:
int32 a = ...; // value of variable irrelevant; can be negative
unsigned char *buf = malloc(4); /* assuming octet bytes, this is just big
enough to hold an int32 */
Существует ли эффективный и переносимый алгоритм для записи дополняющего Биг-эндианского представления a
в 4-байтовый буфер buf
переносимым способом? То есть, независимо от того, как машина, которую мы запускаем, представляет целые числа внутри, как я могу эффективно записать дополняющее представление этих двух a
в буфер?
Это вопрос C , поэтому вы можете полагаться на стандарт C, чтобы определить, если ваш ответ соответствует требованиям переносимости.
3 ответа:
Да, вы, конечно, можете сделать это переносимо:
int32_t a = ...; uint32_t b = a; unsigned char *buf = malloc(sizeof a); uint32_t mask = (1U << CHAR_BIT) - 1; // one-byte mask for (int i = 0; i < sizeof a; i++) { int shift = CHAR_BIT * (sizeof a - i - 1); // downshift amount to put next // byte in low bits buf[i] = (b >> shift) & mask; // save current byte to buffer }
, по крайней мере, я думаю, что это правильно. Я сделаю быстрый тест.
unsigned long tmp = a; // Converts to "twos complement" unsigned char *buf = malloc(4); buf[0] = tmp>>24 & 255; buf[1] = tmp>>16 & 255; buf[2] = tmp>>8 & 255; buf[3] = tmp & 255;
Вы можете отбросить части
& 255
, Если вы предполагаетеCHAR_BIT == 8
.
Если я правильно понимаю, вы хотите сохранить 4 байта
Давайте сначала проясним эти предположения: sizeof (char)=8, комплимент двух и sizeof(int32)=4. Нет, в вашем коде нет переносимого способа, потому что вы пытаетесь преобразовать его вint32
внутри буфера char, в определенном порядке(например, Нижний байт первый), независимо от того, какint32
представляется.char
вместоunsigned char
. Хранение байта вchar
определяется реализацией.Но если вы храните его в
unsigned char
массив, есть переносимые способы. Вы можете каждый раз сдвигать значение вправо на 8 бит, чтобы сформировать байт в результирующем массиве, или с помощью побитового оператора and&:// a is unsigned 1st byte = a & 0xFF 2nd byte = a>>8 & 0xFF 3rd byte = a>>16 & 0xFF 4th byte = a>>24 & 0xFF