Search code examples
cc-preprocessorbitwise-and

C preprocessor compiling anomaly when using "bitwise and"


I have the following program code in a header file for debugging purposes. My intention is to decide during compile time that which messages should be printed out to console port or not print them at all if program is not compiled in debug mode.

#define ALL 0xffffffff    
#define ENABLED  (ERROR | WARNING | INFO)    //Enabled error messages which needs to be printed out.

//Error msg types
#define ERROR         0x1ul
#define WARNING       0x2ul
#define INFO          0x4ul
#define DBG           0x10ul
#define ENTER         0x20ul

#define STORAGE            0x40ul
#define BOND_MANAGER       0x80ul
#define ANCS_EVENT         0x100ul
#define NOTIF_EVENT        0x200ul
#define BLE_EVENT          0x400ul
#define ANCS_APP           0x800ul
#define BLE                0x1000ul
#define PERIPHERALS        0x2000ul
#define PWM                0x4000ul
#define LEDS               0x8000ul

#define DebugMsgStr(a,b) do { \
        if (a & ENABLED) \
            simple_uart_putstring(b); \     //print to console port
    }while(0)

#define DebugMsg(a,...) do { \
        if (a & ENABLED) {\
            uint8_t data[100];          \
            snprintf(data,100,"%x - %x - %x",a,ENABLED,a&ENABLED);  \  //These two lines only used for debugging the debug_printf
            simple_uart_putstring(data); \                             //These two lines only used for debugging the debug_printf
            snprintf(data,100,__VA_ARGS__);  \
            simple_uart_putstring(data); }\     //print to console port
    }while(0)

I print messages in the code like:

DebugMsg(ERROR| BLE ,"[ERROR-BLE]This should be seen",..);
DebugMsg(DBG | BLE ,"[DBG-BLE]This should not been logged",..);

Last message should only be logged when either DBG level or module BLE debugging is enabled. Despite DBG level is not enabled currently, i see the following logs:

8010 - 7 - 8000[LEDS-DBG] effect_counter:2
1010 - 7 - 10[BLE-DBG] Timer Tick: 0x0000745d

so

0x8010 & 0x7 == 0x8000.    
0x1010 & 0x7 == 0x10

How this could happen? I am using arm-gcc for compiling to cortex-m0 nrf51822 Nordic chip. Also there is a dissasambly snippet, but do not seen anything special, just if(a&ENABLED) is not compiled at all.

DebugMsg(DBG | BLE,"[BLE-DBG] Timer Tick: 0x%08x\r\n",currentTime);

R7 --> this probably contains a pointer to currentTime variable

0001587a:   adds r1, r7, #0           -->r1 = r7
0001587c:   adds r1, #12               -->r1 = r1+12

0001587e:   ldr r2, [pc, #248]      ; (0x15978 <ble_ancs_c_connection_moretriage_timer+272>)
00015880:   ldr r3, [pc, #248]      ; (0x1597c <ble_ancs_c_connection_moretriage_timer+276>)

00015882:   movs r0, #7                --> r0 -ba 0x7
00015884:   str r0, [sp, #0]           --> save to stack 

00015886:   movs r0, #16               -->r0 ->ba 0x10
00015888:   str r0, [sp, #4]           --> save to stack

0001588a:   adds r0, r1, #0            --> r0 = r1
0001588c:   movs r1, #100   ; 0x64     --> r1 = 100

0001588e:   bl 0x22c74 <snprintf>
00015892:   adds r3, r7, #0
00015894:   adds r3, #12
00015896:   adds r0, r3, #0
00015898:   bl 0x21a08 <simple_uart_putstring>
0001589c:   ldr r3, [r7, #112]      ; 0x70
0001589e:   adds r1, r7, #0
000158a0:   adds r1, #12
000158a2:   ldr r2, [pc, #220]      ; (0x15980 <ble_ancs_c_connection_moretriage_timer+280>)
000158a4:   adds r0, r1, #0
000158a6:   movs r1, #100   ; 0x64
000158a8:   bl 0x22c74 <snprintf>
000158ac:   adds r3, r7, #0
000158ae:   adds r3, #12
000158b0:   adds r0, r3, #0
000158b2:   bl 0x21a08 <simple_uart_putstring>

Thanks in advance.


Solution

  • DebugMsg(DBG | BLE ,"[ERROR-BLE]This should be seen",..) is expanded as

    if (DBG | BLE & ENABLED) ...
    

    which becomes

    if (0x10ul | 0x1000ul & 0x07)
    

    but & has higher precedence than | so this is parsed as

    if (0x10 | (0x1000 & 0x07))
    

    which is always true.

    You should change the marco to

    #define DebugMsgStr(a,b) do { \
        if ((a) & ENABLED) \