使用位操作来设置一些标志的最佳实践

时间:2012-10-25 21:05:12

标签: objective-c ios bit-manipulation

我想打开/关闭代表难度级别的3颗星。我不想使用几个if条件,是否可以通过使用按位运算来实现?

假设我已经宣布了这样的枚举:

enum 
{
    EASY = 0,
    MODERATE,
    CHALLENGING
} Difficulty;

我想找一个让我找到哪个星打开或关闭的操作:

例如:

level 2 (challenging)
star 0 -> 1
star 1 -> 1
star 2 -> 1

level 1 (moderate)
star 0 -> 1
star 1 -> 1
star 2 -> 0

level 0 (easy)
star 0 -> 1
star 1 -> 0
star 2 -> 0

4 个答案:

答案 0 :(得分:20)

如果您希望有3位来保存星形状态,而不是有三个布尔标志,那么应该这样做:

typedef enum 
{
    DifficultyEasy = 1 << 0,
    DifficultyModerate = 1 << 1,
    DifficultyChallenging = 1 << 2
} Difficulty;

Difficulty state = 0; // default

设置简易:

state |= DifficultyEasy;

添加挑战:

state |= DifficultyChallenging;

重置简易:

state &= ~DifficultyEasy;

要知道挑战集:

BOOL isChallenging =  DifficultyChallenging & state;

如果有人需要解释它是如何工作的:

1 << x means set x bit to 1 (from right);
// actually it means move 0b00000001 left by x, but I said 'set' to simplify it 

1 << 5 = 0b00100000; 1 << 2 = 0b00000100; 1 << 0 = 0b00000001;

0b00001111 | 0b11000011 = 0b11001111 (0 | 0 = 0, 1 | 0 = 1, 1 | 1 = 1)

0b00001111 & 0b11000011 = 0b00000011 (0 & 0 = 0, 1 & 0 = 0, 1 & 1 = 1)

~0b00001111 = 0b11110000 (~0 = 1, ~1 = 0)

答案 1 :(得分:5)

你会想做这样的事情:

typedef enum Difficulty : NSUInteger
{
    EASY = 1 << 0,
    MODERATE = 1 << 1,
    CHALLENGING = 1 << 2
} Difficulty;

然后检查一下:

- (void) setStarsWithDifficulty:(Difficulty)diff
{
    star0 = (diff & (EASY | MODERATE | CHALLENGING));
    star1 = (diff & (MODERATE | CHALLENGING));
    star2 = (diff & CHALLENGING);
}

答案 2 :(得分:1)

你在谈论类似的事情:

star0 = 1
star1 = value & CHALLENGING || value & MODERATE
star2 = value & CHALLENGING

答案 3 :(得分:0)

#define STAR0 1
#define STAR1 2
#define STAR2 4

#define  EASY   STAR0
#define  MODERATE  STAR1|STAR0
#define  CHALLENGING STAR0|STAR1|STAR2

使用和检测值d并与0进行比较将产生所需的映射,上面的一些示例将为您提供映射值,请看一下:

  int d = EASY;
  NSLog(@"Star 0 %d",(d&STAR0)!=0);
  NSLog(@"Star 1 %d",(d&STAR1)!=0);
  NSLog(@"Star 2 %d",(d&STAR2)!=0);
  d=MODERATE;
  NSLog(@"Star 0 %d",(d&STAR0)!=0);
  NSLog(@"Star 1 %d",(d&STAR1)!=0);
  NSLog(@"Star 2 %d",(d&STAR2)!=0);
  d=CHALLENGING;
  NSLog(@"Star 0 %d",(d&STAR0)!=0);
  NSLog(@"Star 1 %d",(d&STAR1)!=0);
  NSLog(@"Star 2 %d",(d&STAR2)!=0);