#define IDLE_WORK() { ; }


Joined
Mar 21, 2022
Messages
2
Reaction score
0
Hey.

I'm looking into some code and see this line:
#define IDLE_WORK() { ; }

Is this a macro and what does "{ ; }" do? Does anyone got some keywords so i an google it and read about it?


Thanks
- Jacob
 
Ad

Advertisements

Joined
Mar 3, 2021
Messages
243
Reaction score
29
Yes, this is indeed a (preprocessor) macro. The way macros work in C is that they are literally string substitutions placed into the code and compiled after. It's... not ideal. They're hard to debug, not type safe, and mess up line numbers in compiler errors. So, this macro, which takes no arguments (due to: ()), will put, literally, { ; } wherever you call that macro. That code does nothing. It's not even a no-op, it will not actually add assembly code to the binary. Take this example:

C:
#include <stdio.h>


#define IDLE_WORK() { ; }

void main(){
        printf("start\n");
        IDLE_WORK();
        printf("end\n");
}

and this code that it is assembled into:

Code:
main:
.LFB0:
        .file 1 "noop_test.c"
        .loc 1 6 12
        .cfi_startproc
        pushq   %rbp    #
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp      #,
        .cfi_def_cfa_register 6
# noop_test.c:7:        printf("start\n");
        .loc 1 7 2
        movl    $.LC0, %edi     #,
        call    puts    #
# noop_test.c:9:        printf("end\n");
        .loc 1 9 2
        movl    $.LC1, %edi     #,
        call    puts    #
# noop_test.c:10: }
        .loc 1 10 1
        nop
        popq    %rbp    #
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc

The two sections below each of the printfs are the same and there are no extra instructions generated between them for the macro.

Macros are commonly used to define constants. That's a pretty decent way to use them, though that's not terribly type safe. Sometimes, it's used for an arbitrary amount of code. In this case, the most idiomatic way to write a macro is thus:

C:
#define MY_AWESOME_BLOCK() do { /* CODE HERE */ } while(0)

The reason for this is that it can be used in a place that expects a single expression OR a block AND it requires a trailing semi-colon, which makes it act like a normal expression (and could one day be replaced by a non-macro function call later without changing any calling code). Take, for example:

C:
if (1 == 0){
    printf("physics exploded\n");
} else MY_AWESOME_BLOCK();

If you had multiple lines in a macro but didn't wrap it in a block like the above, only the first line would be part of the else block and the rest would be one level up, which is most certainly not the intent. Macros are messy. Tread carefully.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top