Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For loop macro which unrolled on the pre-processor phase?

I want to use gcc pre-processor to write almost the same code declaration for 500 times. let's say for demonstration purposes I would like to use a macro FOR_MACRO:

#define FOR_MACRO(x) \
    #for i in {1 ... x}: \
        const int arr_len_##x[i] = {i};

and calling FOR_MACRO(100) will be converted into:

const int arr_len_1[1] = {1};
const int arr_len_2[2] = {2};

...

const int arr_len_100[100] = {100};
like image 549
0x90 Avatar asked Oct 01 '13 13:10

0x90


4 Answers

This is not a good idea:

While possible in principle, using the preprocessor means you have to manually unroll the loop at least once, you end up with some arbitrary implementation-defined limit on loop depth and all statements will be generated in a single line.

Better use the scripting language of your choice to generate the code (possibly in a separate includeable file) and integrate that with your build process.

like image 59
Christoph Avatar answered Nov 13 '22 02:11

Christoph


You can use Order-PP for this, if you desperately need to.

It's a scripting language implemented in the preprocessor. This means it's conceptually similar to using a scripting language to generate C code (in fact, the same) except there are no external tools and the script runs at the same time as the C compiler: everything is done with C macros. Despite being built on the preprocessor, there are no real limits to loop iterations, recursion depth, or anything like that (the limit is somewhere in the billions, you don't need to worry about it).

To emit the code requested in the question example, you could write:

#include <order/interpreter.h>

ORDER_PP(    // runs Order code
  8for_each_in_range(8fn(8I,
                         8print( 8cat(8(const int arr_len_), 8I)
                                   ([) 8I (] = {) 8I (};) )),
                     1, 101)
)

I can't fathom why you would do this instead of simply integrating an external language like Python into your build process (Order might be implemented using macros, but it's still a separate language to understand), but the option is there.

Order only works with GCC as far as I know; other preprocessors run out of stack too quickly (even Clang), or are not perfectly standard-compliant.

like image 36
Leushenko Avatar answered Nov 13 '22 00:11

Leushenko


Instead of providing you with a solution for exactly your problem, are you sure it cannot be handled in a better way?

Maybe it would be better to

  • use one array with one more dimension
  • fill the data with the help of an array at runtime, as you obviously want to fill out the first entry of each array. If you leave the array uninitialized, it will (provided it is defined on module level) be put into .bss segment instead of .data and will probably need less space in the binary file.
like image 41
glglgl Avatar answered Nov 13 '22 00:11

glglgl


You could use e.g P99 to do such preprocessor code unrolling. But because of the limited capacities of the preprocessor this comes with a limit, and that limit is normally way below 500.

like image 1
Jens Gustedt Avatar answered Nov 13 '22 02:11

Jens Gustedt