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

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

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

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

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

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

1

Решение

Для 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       |
+---+---+---+---+---+---+---+---+
4

Другие решения

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

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

0

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

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
0