Получение 32-битных слов из 64-битных значений в C / C ++ и не беспокоиться о порядке байтов - PullRequest
10 голосов
/ 03 февраля 2010

Насколько я понимаю, в C / C ++ побитовые операторы должны быть независимыми от порядка байтов и вести себя так, как вы ожидаете. Я хочу убедиться, что я действительно получаю наиболее значимые и наименее значимые слова из 64-битного значения, и не беспокоиться о порядке байтов в машине. Вот пример:

uint64_t temp;
uint32_t msw, lsw;
msw = (temp & 0xFFFFFFFF00000000) >> 32;
lsw = temp & 0x00000000FFFFFFFF;

Будет ли это работать?

Ответы [ 8 ]

17 голосов
/ 03 февраля 2010

6.5.7 Операторы побитового сдвига

4 Результатом E1 << E2 является E1 сдвинутые влево битовые позиции E2; освобождено биты заполнены нулями. Если E1 имеет тип без знака, значение результат E1 × 2E2, уменьшенный по модулю один больше максимального значения представимый в типе результата. Если E1 имеет подписанный тип и неотрицательный значение, а E1 × 2E2 представимо в типе результата, то это итоговое значение; в противном случае поведение не определено. </p>

Итак, да - гарантировано стандартом.

3 голосов
/ 04 февраля 2010

Это будет работать, но странная склонность некоторых авторов делать битовую маскировку перед битовой сменой всегда меня озадачивала.

На мой взгляд, гораздо более элегантный подход - это тот, который делает сдвиг первым

msw = (temp >> 32) & 0xFFFFFFFF; 
lsw = temp & 0xFFFFFFFF; 

хотя бы потому, что каждый раз использует одну и ту же «магическую» константу битовой маски.

Теперь, если ваш целевой тип не подписан и уже имеет желаемую ширину в битах, маскирование становится совершенно ненужным

msw = temp >> 32; 
lsw = temp; 
3 голосов
/ 03 февраля 2010

Да, это должно работать. Когда вы извлекаете msw, ваша маска на самом деле не достигает больших результатов - биты, которые вы маскируете на ноль, будут сброшены, когда вы все равно сделаете сдвиг. Лично я бы, наверное, использовал что-то вроде этого:

uint32_t lsw = -1, msw = -1;
lsw &= temp;
msw &= temp >> 32;

Конечно, чтобы получить значимый результат, нужно инициализировать temp, чего не было в вашем коде.

2 голосов
/ 03 февраля 2010

Да.Это должно работать.

1 голос
/ 04 февраля 2010

Endianness - это расположение памяти. Сдвиг - это биты (и битовая разметка). Значение слова касается разметки, а не разметки памяти. Так что порядок байтов не имеет ничего общего со значением слова.

1 голос
/ 03 февраля 2010

Просто мысль, которой я хотел бы поделиться, возможно, вы могли бы обойти бесконечность значения, используя функции или макросы, найденные в <arpa/inet.h>, чтобы преобразовать сеть в порядок хостов и наоборот, можно сказать, чтоон больше используется в сочетании с сокетами, но его можно использовать для этого экземпляра, чтобы гарантировать, что значение, такое как 0xABCD от другого процессора, по-прежнему равно 0xABCD на Intel x86, вместо того чтобы прибегать к ручным кодированным пользовательским функциям для работы с порядком байтовархитектура ....?!

Редактировать: Вот статья о Endianess на CodeProject и автор разработал макросы для работы с 64-битными значениями.

Надеюсь, это поможет, С уважением, Том.

0 голосов
/ 03 февраля 2010

В дополнение к другим ответам, я добавлю, что вам не следует беспокоиться о порядке байтов в C. Проблема с порядком байтов возникает только при просмотре некоторых байтов под типом, отличным от того, который использовался для записи этих байтов в первую очередь.Когда вы делаете это, вы очень близки к тому, чтобы иметь проблемы с псевдонимами, что означает, что ваш код может сломаться при использовании другого компилятора или другого флага оптимизации.

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

0 голосов
/ 03 февраля 2010

Я думаю, что то, что вы говорите, совершенно верно, но с чего это вам?

Если у вас есть какие-то буквальные значения, то вы знаете, какой конец какой. Но если вы обнаружите, что у вас есть значения, полученные из-за пределов программы, вы не можете быть в этом уверены, если они не были каким-то образом закодированы.

...