как замаскировать «верхнюю половину» длинного int - PullRequest
3 голосов
/ 25 июня 2009

У меня есть вопрос о построении битовых масок в C. Мне нужно замаскировать наименее значимую половину long int, чтобы у меня осталась только верхняя половина. Мне нужно убедиться, что он маскирует half независимо от того, на какой я 64-битной или 32-битной платформе. Я вижу, что __WORD_SIZE определен в limit.h. Первоначально я делаю это так:

#define UPPER(X) ( X & ( ~0 << (__WORDSIZE/2) ) )

Какой самый правильный и эффективный способ сделать это?

Ответы [ 4 ]

13 голосов
/ 25 июня 2009

Я бы посоветовал вам использовать что-то вроде

#define UPPER(x) (x & (~0 << (sizeof(x) * 4)))

Это будет работать, даже если limit.h отсутствует или если по какой-то причине __WORDSIZE не определено. Кроме того, он также будет работать для других типов, так что вы можете, например, используйте его для int, short, char и т. д.
Любой приличный компилятор вычислит значение

sizeof(x) * 4

во время компиляции (так как они оба являются константами), что означает, что вам не нужно беспокоиться о каком-либо падении производительности.

EDIT: исправлена ​​ошибка - sizeof возвращает размер в байтах, а не в битах, поэтому мы должны умножить на 4 (8/2), чтобы получить правильный результат. Спасибо тем, кто указал на это.

РЕДАКТИРОВАТЬ 2: Если вы хотите быть действительно педантичным, вы можете использовать

#define UPPER(x) (x & (~0 << (sizeof(x) * CHAR_BITS / 2)))

CHAR_BIT - это константа, определенная в limit.h - она ​​определяет количество битов в символе и зависит от платформы. Тем не менее, это не является необходимым (в общем случае), поскольку в AFAIK нет платформ, которые обычно используют банкоматы, использующие байты нестандартного размера.

3 голосов
/ 25 июня 2009
#define UPPER(X) ( (X) & ( ~0L << ( ( sizeof(long) * CHAR_BIT ) / 2 ) ) )
1 голос
/ 25 июня 2009

Я стараюсь не быть умным. Я бы сделал что-то вроде этого:

static inline int UPPER(long int x) {
if (sizeof(long int) == 8)
  return x & 0xffffffff00000000;
else if (sizeof(long int) == 4)
  return x & 0xffff0000;
}

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

1 голос
/ 25 июня 2009

То, что у тебя есть, хорошо. Постоянное распространение сведет ( ~0 << (__WORDSIZE/2) ) в одно значение, при условии, что __WORDSIZE является постоянной величиной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...