简体   繁体   English

C-为什么用&而不是switch / if比较常数?

[英]C - Why compare constants with & instead of switch/if?

I am reading the OpenSL documentation for Android. 我正在阅读Android的OpenSL文档。 Quoting the following document: http://mobilepearls.com/labs/native-android-api/ndk/docs/opensles/ 引用以下文档: http : //mobilepearls.com/labs/native-android-api/ndk/docs/opensles/

"Callback handlers should be prepared to be called more or less frequently, to receive additional event types, and should ignore event types that they do not recognize. Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously. Use "&" to test for each event bit rather than a switch case. " “应准备好或多或少地频繁调用回调处理程序,以接收其他事件类型,并且应忽略它们无法识别的事件类型。使用启用的事件类型的事件掩码配置的回调应准备使用同时设置多个事件类型位。 使用“&”测试每个事件位,而不要使用开关盒。

Checking the official specification of OpenSL ( https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf ), there are these 3 constants defined I am interested in: 检查OpenSL的官方规范( https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf ),定义了以下三个常量,我感兴趣:

SL_PREFETCHSTATUS 

#define SL_PREFETCHSTATUS_UNDERFLOW          ((SLuint32) 0x00000001) 
#define SL_PREFETCHSTATUS_SUFFICIENTDATA     ((SLuint32) 0x00000002) 
#define SL_PREFETCHSTATUS_OVERFLOW           ((SLuint32) 0x00000003)

If I understood correctly, the quote above says to compare using &, like this: 如果我理解正确,上面的引言说使用&进行比较,如下所示:

if(status & SL_PREFETCHSTATUS_UNDERFLOW) doSomething_1();
if(status & SL_PREFETCHSTATUS_SUFFICIENTDATA) doSomething_2();
if(status & SL_PREFETCHSTATUS_OVERFLOW) doSomething_3();

Instead of a switch case: 代替开关盒:

switch(statusCode){

    case(SL_PREFETCHSTATUS_UNDERFLOW): doSomething_1(); break;
    case(SL_PREFETCHSTATUS_SUFFICIENTDATA): doSomething_2(); break;
    case(SL_PREFETCHSTATUS_OVERFLOW): doSomething_3(); break;
}

Now, I don't understand why that is exactly. 现在,我不明白为什么会这样。 Can anyone explain me the reason? 谁能解释我的原因?

PS: If the constants were defined in multiples of 2, like this: PS:如果常量定义为2的倍数,则如下所示:

#define SL_PREFETCHSTATUS_UNDERFLOW          ((SLuint32) 0x00000001) 
#define SL_PREFETCHSTATUS_SUFFICIENTDATA     ((SLuint32) 0x00000002) 
#define SL_PREFETCHSTATUS_OVERFLOW           ((SLuint32) 0x00000004)

It would make sense, but the specification defines the last constant as 0x00000003 instead of 0x00000004, so I am lost. 这是有道理的,但是规范将最后一个常量定义为0x00000003而不是0x00000004,所以我迷路了。

That comment is in reference to the event constants. 该注释引用了事件常量。 What you're looking at are not event constants, but rather status constants. 您正在查看的不是事件常量,而是状态常量。 Event constants would be for example: 事件常量例如:

#define SL_PLAYEVENT_HEADATEND ((SLuint32) 0x00000001)
#define SL_PLAYEVENT_HEADATMARKER ((SLuint32) 0x00000002)
#define SL_PLAYEVENT_HEADATNEWPOS ((SLuint32) 0x00000004)
#define SL_PLAYEVENT_HEADMOVING ((SLuint32) 0x00000008)
#define SL_PLAYEVENT_HEADSTALLED ((SLuint32) 0x00000010)

You can see these are bitmask values and could be combined. 您可以看到这些是位掩码值,可以合并使用。 Since they can be combined you need to compare the individual bits rather than the whole value to ensure you correctly match against the events you're interested in. 由于可以将它们组合在一起,因此您需要比较单个位而不是整个值,以确保您正确匹配感兴趣的事件。

The documentation makes it clear: 该文档明确指出:

Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously. 使用启用的事件类型的事件掩码配置的回调应准备好在同时设置多个事件类型位的情况下进行调用。

This means that despite the flags not being bitwise, there still remains the possibility that multiple flags are set. 这意味着尽管标志不是按位的,但仍然存在设置多个标志的可能性。 The other flags being set might not necessarily be publicly-defined, but could be private, reserved or otherwise undocumented but still necessary for the system to function. 设置的其他标志可能不一定是公共定义的,而是可以是私有的,保留的或未记录的,但对于系统运行而言仍然是必需的。

...so using a switch is not a good idea because then this fails: ...所以使用开关不是一个好主意,因为这样会失败:

SLuint32 statusCode = SL_PRIVATE_RESERVED_INTERNAL_USE_ONLY | SL_PREFETCH_STATUS_UNDERFLOW;
switch( statusCode ) {
    case SL_PREFETCH_STATUS_UNDERFLOW:
        // this code will never be executed
        break;
}

Using & does bitwise comparison. 使用&按位比较。 So a & b gives a non-zero results if any of the bits are set in both a and b . 因此a & b如果在ab都设置了任何位,则a & b会给出非零的结果。 That is not the same as comparing the values (for a given non-zero value of a , there are multiple values of b that can give a match). 这与比较值不同(对于给定的a的非零值, b多个值可以给出匹配项)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM