Как получить более высокие 20 бит из 64-битного целого числа?

Я использую 64-битную Mac OS X, у меня есть NSUInteger (или uint64, в моей системе это не имеет значения).

Как получить более высокие 20 бит NSUInteger и сохранить их в другом NSUInteger?

Вы можете ответить, как это сделать в C, C++ или Objective-C.

P.S. Пожалуйста, не говорите мне изменить весь код и вместо этого использовать битовые поля.

П.П.С. Я думаю, мне нужно использовать битовую маску и сдвиг?


person Victor Polevoy    schedule 20.01.2014    source источник
comment
Разве вы не хотите просто i >> 44? Или (i >> 44) & 0xFFFFF, если NSUInteger может быть больше 64.   -  person ikegami    schedule 20.01.2014
comment
Да, конечно. Спасибо.   -  person Victor Polevoy    schedule 20.01.2014


Ответы (3)


Для uint64_t вы можете просто использовать

i >> 44

Для подписанных типов или типов, длина которых может превышать 64 бита, вам также потребуется маскировать старшие биты.

(i >> 44) & 0xFFFFF

Пример меньшего масштаба,

4 bits starting at pos 2 of 8.

  7   6   5   4   3   2   1   0
+---+---+---+---+---+---+---+---+
| ? | ? |       j       | ? | ? |
+---+---+---+---+---+---+---+---+

                             >> 2

+---+---+---+---+---+---+---+---+
| * | * | ? | ? |       j       |   * = 0 if unsigned or original bit7 if signed.
+---+---+---+---+---+---+---+---+ 

                   & ( 2**4 - 1 )

+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 |       j       |
+---+---+---+---+---+---+---+---+
person ikegami    schedule 20.01.2014
comment
+1 - Хорошее изображение ASCII, показывает, что битовая манипуляция - это форма изображения. - person Thomas Matthews; 21.01.2014

uint64 original = ...;
uint64 another = ((0xFFFFF00000000000 & original) >> 44);

Сначала и с битовой маской, затем переместитесь вправо на 44 бита.

person m. c.    schedule 20.01.2014
comment
Если вы сначала сдвинете, а затем замаскируете его, у вас будет меньше шансов сделать ошибку при вводе константы. - person Ferruccio; 20.01.2014
comment
Первая маскировка также не будет работать для подписанных типов. - person ikegami; 20.01.2014

Я не знал о проблеме со сдвигом сначала для чисел со знаком. Это функция, зависящая от реализации? Кажется, не имеет большого значения, переключаетесь ли вы до или после для подписанного или неподписанного для моей реализации:

int main()
{
  uint64_t a = std::numeric_limits<uint64_t>::max();
  int64_t  b = std::numeric_limits<int64_t>::max();
  uint64_t c = std::numeric_limits<uint64_t>::max();
  int64_t  d = std::numeric_limits<int64_t>::max();

  a = (0xFFFFF00000000000 & a) >> 44;
  b = (0xFFFFF00000000000 & b) >> 44;
  c = 0xFFFFF & (c >> 44);
  d = 0xFFFFF & (d >> 44);
  cout << "a = " << a << "; c = " << c << "; a?=c = " << (a==c) << endl;
  cout << "b = " << b << "; d = " << b << "; b?=d = " << (b==d) << endl;

  return 0;
}

Это производит:

a = 1048575; c = 1048575; a?=c = 1
b = 524287; d = 524287; b?=d = 1

$ c++ --version
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
person Gabriel Perdue    schedule 20.01.2014