Search code examples
cswitch-statementcomparisonampersandopensl

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


I am reading the OpenSL documentation for Android. Quoting the following document: 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:

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:

#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.


Solution

  • 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.