2013-08-15 2 views
2

Скажет, у меня есть следующий:Алгоритм написать дополнение до два числа в памяти переносимого

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 в , чтобы определить, если ваш ответ соответствует требованиям портативности.

+0

использовать int вместо int32. Я считаю, что int - это комплимент 2. Кроме того, endianess имеет значение только тогда, когда вы разговариваете с другим компьютером, проходящим через межсетевые данные. если это проблема, тогда вам нужно выполнить проверку подлинности на этой машине, чтобы убедиться, что она совместима. сделайте это с помощью passin в char '1' и отправьте им значение int для' 1'. Имеет ли это смысл? –

+0

@PaulNikonowicz: стандарт C не требует, чтобы 'int' был дополнением двух. В этом случае конечная величина имеет значение, потому что мы говорим о написании целого числа в символьном буфере, и мы не хотим, чтобы число было написано «назад». –

+0

буфер символов избавит вас от проблемы с контентом. –

ответ

2

Да, можно, конечно, сделать это переносимо:

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 
} 

По крайней мере, я думаю, что это правильно. Я сделаю быстрый тест.

+0

Вы делаете это слишком сложно. «Преобразование в дополнение к двум» - это просто операция преобразования в беззнаковый тип, который может охватывать весь диапазон. –

+0

Это правда; который очистит несколько строк. «Жесткая часть» - это последний бит в цикле. –

+0

Отредактировано; он работает сейчас в нескольких тестах здесь. Я сломаю последний бит, чтобы было ясно, что происходит. –

0

Если я правильно понимаю, вы хотите сохранить 4 байта int32 внутри буфера символа в определенном порядке (например, младший байт первым), независимо от того, как представлен int32.

Давайте сначала разъясним эти предположения: sizeof (char) = 8, комплимент двух и sizeof (int32) = 4.

Нет, в вашем коде нет портативного способа, поскольку вы пытаетесь преобразовать его в char вместо unsigned char. Хранение байта в char определяется реализацией.

Но если вы храните его в массиве unsigned char, есть переносные способы. Вы можете прямо сдвинуть значение каждый раз, когда на 8 бит, чтобы сформировать байты в результирующем массиве, или с побитовым и оператором &:

// a is unsigned 
1st byte = a & 0xFF 
2nd byte = a>>8 & 0xFF 
3rd byte = a>>16 & 0xFF 
4th byte = a>>24 & 0xFF 
+0

Фактически определенная реализация, а не неопределенная. –

+0

если 'char' - неподписанный тип, это нормально. –

+0

@R .. Правильно. Обновлено. –

2
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.

+0

Отличный вариант 'unsigned long' был очень полезен - он стал намного проще (+1) –