2013-03-29 6 views
1

Я не специалист по C/C++.В чем смысл этой декларации?

Я нашел это заявление сегодня:

typedef NS_OPTIONS(NSUInteger, PKRevealControllerType) 
{ 
    PKRevealControllerTypeNone = 0, 
    PKRevealControllerTypeLeft = 1 << 0, 
    PKRevealControllerTypeRight = 1 << 1, 
    PKRevealControllerTypeBoth = (PKRevealControllerTypeLeft | PKRevealControllerTypeRight) 
}; 

Можете ли вы, ребята, перевести то, что ценности каждое значение будет иметь?

+1

Похоже Objective C, а не C++ – jedwards

+0

На каком языке? Нет такого языка, как C/C++, и это похоже на другой язык. А как насчет этого макроса? Что такое 'NS_OPTIONS'? –

+0

забыть об этом. Я хотел бы знать, какие значения будут иметь значения из всех трех других значений. Что 1 << 0, 1 << 1, а третий будет производиться? – SpaceDog

ответ

5

Оператор << есть Побитовый Оператор сменной или сменной. Сдвиг всех битов влево на заданное количество раз: (арифметический сдвиг влево и резервы знаковый бит)

m << n 

Сдвиг всех битов m налево в n число раз.(извещение одна смена == умножить на два).

1 << 0 означает нет сдвиг так, чтобы он равнялся 1.

1 << 1 означает один сдвиг так, что он равен 1*2 = 2.

Я объясняю один байт: один в один байт, как:

MSB 
+----+----+----+---+---+---+---+---+ 
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |  1 
+----+----+----+---+---+---+---+---+ 
    7  6 5 4 3 2 1/0 
    |       /   1 << 1 
    |       | 
    ▼       ▼ 
+----+----+----+---+---+---+---+---+ 
| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |  2  
+----+----+----+---+---+---+---+---+ 
    7 6 5 4 3 2 1 0 

В то время как 1 << 0 не делать ничего, кроме как его фигура одного. (Уведомление седьмой бит копируется сохранить знак)

оператор ИЛИ: сделать немного мудрым или

MSB       PKRevealControllerTypeLeft 
+----+----+----+---+---+---+---+---+ 
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | == 1 
+----+----+----+---+---+---+---+---+ 
    7 6 5 4 3 2 1 0 
    | | | | | | | |  OR 
MSB        PKRevealControllerTypeRight 
+----+----+----+---+---+---+---+---+ 
| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | == 2 
+----+----+----+---+---+---+---+---+ 
    7 6 5 4 3 2 1 0 

= 

MSB     PKRevealControllerTypeBoth 
+----+----+----+---+---+---+---+---+ 
| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | == 3 
+----+----+----+---+---+---+---+---+ 
    7 6 5 4 3 2 1 0 

| является немного мудрый оператор. ниже в коде or1 | 2 == 3

PKRevealControllerTypeNone = 0,    // is Zero 
PKRevealControllerTypeLeft = 1 << 0,  // one 
PKRevealControllerTypeRight = 1 << 1,  // two 
PKRevealControllerTypeBoth = (PKRevealControllerTypeLeft |  
          PKRevealControllerTypeRight) // three 

Существует не более техническая причина инициализируются значениями, как это, определяя, как это делает вещи выстраиваться красиво этот ответ: define SOMETHING (1 << 0)

оптимизации компилятор преобразует их в проще, как: (Я не уверен, что для третьего, но я думаю, что компилятор оптимизирует это слишком)

PKRevealControllerTypeNone = 0,  // is Zero 
PKRevealControllerTypeLeft = 1,  // one 
PKRevealControllerTypeRight = 2,  // two 
PKRevealControllerTypeBoth = 3,  // Three 

Редактировать: @thanks to Till. этот ответ App States with BOOL flags показывает полезность объявлений, которые вы получили с помощью бит-мудрых операторов.

+0

было не проще установить его как 0, 1, 2, 3? Есть ли причина быть безумной? – SpaceDog

+0

Это дает понять, что это набор бит-флагов –

+0

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

3

Это перечисление битовых флагов:

PKRevealControllerTypeNone = 0  // no flags set 
PKRevealControllerTypeLeft = 1 << 0, // bit 0 set 
PKRevealControllerTypeRight = 1 << 1, // bit 1 set 

А потом

PKRevealControllerTypeBoth = 
    (PKRevealControllerTypeLeft | PKRevealControllerTypeRight) 

только результат побитового ИЛИ-два флага. Итак, бит 0 и бит 1 установлены.

Оператор << - оператор сдвига влево. И оператор | побитовое ИЛИ.

В целом полученные значения:

PKRevealControllerTypeNone = 0 
PKRevealControllerTypeLeft = 1 
PKRevealControllerTypeRight = 2 
PKRevealControllerTypeBoth = 3 

Но это делает намного больше смысла думать об этом в терминах флагов битов. Или как набор, где универсальный набор: {PKRevealControllerTypeLeft, PKRevealControllerTypeRight}

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

2

Все это сводится к поразрядной арифметике.

PKRevealControllerTypeNone имеет значение 0 (двоичных 0000)

PKRevealControllerTypeLeft имеет значение 1 (двоичных 0001)

PKRevealControllerTypeRight имеет значение 2 (двоичных 0010), поскольку 0001 сдвигается влево 1 биты 0010

PKRevealControllerTypeBoth имеет значение 3 (двоичный 0011) с 0010 | 0001 (или работает как сложение) = 0011

В контексте это наиболее вероятно используется для определения значения. Свойство & (или bitwise-and) работает подобно умножению. Если 1 и с номером, то номер сохраняется, если 0 и с номером, то номер очищается.

Таким образом, если вы хотите проверить, если конкретный контроллер специально типа Left и имеет значение 0010 (т.е. тип Right) 0010 & 0001 = 0, который является ложным, как мы ожидаем, что (таким образом, вы определили, что это не правильный тип). Однако, если контроллер Both0011 & 0001 = 1, поэтому результат верен, что является правильным, так как мы определили его тип Both.

+0

0000, 0001, 0010, 0011 ...? было проще установить его как 0, 1, 2, 3? Есть ли причина быть безумной? – SpaceDog

+0

Я добавил еще к своему ответу - вы можете видеть, как это используется на практике. – RageD

+0

@DesperateDeveloper: Увидев номер типа «2», вы не можете легко определить, какие бит (ы) установлены в этом номере. Выражения влево-сдвиге. Это становится важным, если вы печатаете значение переменной PKRevealControllerType и хотите знать, какие параметры установлены в ней; вы можете вставить номер в калькулятор, переключиться в режим программиста и посмотреть на отображение битов. –

2

Это выглядит как Objective C и не C++, но независимо от того:

1 << 0 

только один bitshifted влево (вверх) на 0 позиций. Любое целое число «< < 0» - это просто само.

Так

1 << 0 = 1 

Аналогично

1 << 1 

только один bitshifted влево на 1 позицию. Что вы могли бы представить себе множество способов, но проще всего умножить на 2. [Примечание 1]

Так

x << 1 == x*2 

или

1 << 1 == 2 

Наконец единственный оператор труба является bitwise or.

Так

1 | 2 = 3 

TL; др:

PKRevealControllerTypeNone = 0 
PKRevealControllerTypeLeft = 1 
PKRevealControllerTypeRight = 2 
PKRevealControllerTypeBoth = 3 

[1] Существуют некоторые ограничения на это обобщение, например, когда x равен или больше 1/2 наибольшего значения который может храниться по типу данных.

+0

было не проще установить его как 0, 1, 2, 3? Есть ли причина быть безумной? – SpaceDog

+0

@DesperateDeveloper Значения - это флаги, а не числа.Эта настройка делает очевидным, что каждый флаг независим, а последний - комбинацией двух других. Если у вас было 20 флагов, «нормальным» номерам было бы сложно управлять; что делает 65544? В этой форме я бы знал, что это '(1 << 16) | (1 << 3) ', что означает, что он представляет 2 флага. Просто изучите операторы с битрейтом, и это уже не «безумно». – Dave

+0

Ну, он компилируется по одному и тому же коду, поэтому единственное различие заключается в том, как оно выражается в источнике. Я думаю, что этот подход, вероятно, лучше, чем 0,1,2,3. Три вещи заставляют его выглядеть странно, но [1], что они определили отдельное значение для «None» (0). Это делается не так часто. [2] Чтобы они определили отдельную переменную для (1 | 2). Обычно это тоже не делается. Обычно десятичные значения флагов возрастают по степеням 2 - 1,2,4,8,16 и т. Д. И [3], в битовом поле используется только 2 бита. Часто их гораздо больше. – jedwards

Смежные вопросы