【问题标题】:Assigning values to NSUInteger using the | (OR) operator?使用 | 为 NSUInteger 赋值(OR) 运算符?
【发布时间】:2012-08-13 01:08:04
【问题描述】:

我正在阅读 Apple 关于 NSDate 的文档。在他们的一个代码示例中,我看到了以前从未见过的东西: doc link。这是示例代码。

NSDate *startDate = ...;
NSDate *endDate = ...;

NSCalendar *gregorian = [[NSCalendar alloc]
                 initWithCalendarIdentifier:NSGregorianCalendar];

NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;

NSDateComponents *components = [gregorian components:unitFlags
                                          fromDate:startDate
                                          toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];

我真的对 (OR) | 的使用感到困惑。将值分配给 unitFlags 时的运算符。有人能告诉我那里发生了什么吗?他们都被分配了还是先检查,如果 nil 寻找另一个?提前谢谢你。

【问题讨论】:

    标签: objective-c integer bit-manipulation


    【解决方案1】:

    这不是 OR 运算符 (||)。那是按位或运算符,可能是您理解的问题。

    如果您查看您使用的枚举的定义,您会发现它们是为了兼容性而定义的,基本枚举是CFCalendarUnit。 那么让我们看一下sn-p 对CFCalendarUnit的定义

    kCFCalendarUnitEra = (1UL << 1),
    kCFCalendarUnitYear = (1UL << 2),
    kCFCalendarUnitMonth = (1UL << 3),
    kCFCalendarUnitDay = (1UL << 4),
    

    查看枚举分配给的值:

    kCFCalendarUnitEra = 1 leftShifted once = 2            = 00010
    kCFCalendarUnitYear = 1 leftShifted twice = 4          = 00100
    kCFCalendarUnitMonth = 1 leftShifted three times = 8   = 01000
    kCFCalendarUnitDay = 1 leftShifted four times = 16     = 10000
    

    请注意,每个二进制结果中只有一 (1) 个。

    使用按位或运算符:

    NSUInteger unitFlags = (NSMonthCalendarUnit | NSDayCalendarUnit)
    unitFlags = 01000 (bitwise-OR) 10000
    

    “按位”表示取每个位并执行操作,在这种情况下为 OR

    01000 |
    10000 
    =====
    11000
    

    然后您将此值传递给您的日历,它将使用如下命令解码信息:

    if (unitFlags & kCFCalendarUnitMonth == kCFCalendarUnitMonth) //Where & is the bitwise-AND operator
    
    11000 &    //Unit Flags
    01000      //Value of Month
    =====
    01000      //If unit flags contains month flag, month flag is returned.
    

    使用这种技术。您可以通过“标记”每个位在单个 32 位 int 中存储 32 条布尔信息,并快速组合和检索信息。这避免了以下方法:

    NSDateComponents *components = [gregorian 
                                          hasEraUnit:NO
                                          hasYearUnit:NO
                                          hasMonthUnit:YES
                                          hasDayUnit:YES
                                          hasHourUnit:NO
                                          ....
                                          hasYearForWeekOfYearUnit:NO
                                          fromDate:startDate
                                          toDate:endDate options:0];
    

    【讨论】:

    • 精彩的详细解释!惊人的。谢谢。
    【解决方案2】:

    他们使用这个数字作为标志。基本上,接收器将在标志上查找哪些位为 1。例如,假设您使用整数的前 4 位作为标志,您将查看这些数字中的哪些是 1,哪些是零,以了解激活了标志的哪些元素。这允许您使用相同的变量来有效地传递多条信息。

    【讨论】:

    • 感谢您的回答。我仍然想知道在所示的特定示例中这是如何工作的。在功能层面上,我只是将两个整数放入一个变量中(使用|),然后当我稍后调用它时它们会再次弹出?如果我理解正确,它们是否按照放入的顺序出现,有什么限制?我可以分配三个变量吗?
    • 您可以使用这种操作,例如,保存事件重复的月份。您可以说 LSB 是一年中的第一个月,因此,如果您有数字 1(000000000001 基数 2),则表示只有 1 月处于活动状态。如果你有 17 (000000010001 base 2),意味着你有 1 月和 5 月。如果您看到这一点,您就会意识到您可以使用位标志传递大量信息(取决于上下文)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 2011-08-02
    • 2019-10-06
    • 1970-01-01
    • 2011-11-16
    • 2013-11-30
    相关资源
    最近更新 更多