Andrew Wagner
Andrew Wagner

Reputation: 24577

Use C preprocessor to create a statically sized array based on later expansions

I am trying to manually instrument some C or C++. To do this I would like to declare some structs with statically sized arrays sized to the number of timing statements I manually insert later in the file. A trivial version for illustration:

double array[NUM_TIMESTAMPS];
#define TIMESTAMP() array[__COUNTER__] = get_timestamp();
TIMESTAMP()
TIMESTAMP()
#define NUM_TIMESTAMPS __COUNTER__

With cpp -P this expands to:

double array[NUM_TIMESTAMPS];
array[0] = get_timestamp();
array[1] = get_timestamp();

This will, of course, not pass the compiler because NUM_TIMESTAMPS doesn't get expanded in the c preprocessor's single pass. Is there a way to either defer the expansion of NUM_TIMESTAMPS to a second parsing, or declare the arrays later in the file? Code with this sort of instrumentation will not go into production, so dirty hacks are welcome.

Upvotes: 3

Views: 122

Answers (2)

Russ Schultz
Russ Schultz

Reputation: 2689

I think if you do something like:

extern double array [];

#define TIMESTAMP() array[__COUNTER__] = get_timestamp();
TIMESTAMP()
TIMESTAMP()
#define NUM_TIMESTAMPS __COUNTER__
double array[NUM_TIMESTAMPS];

In this case, the array is defined with enough information so that the resulting TIMESTAMP() expansions can write to it. The final declaration gives the compiler/linker the size of the array.

It should compile and link properly. I don't have a compiler with support for __COUNTER__ available at the moment, so I can't test it.

Upvotes: 0

Alex
Alex

Reputation: 10126

You can try using of extern array:

extern double array[];    
#define TIMESTAMP() array[__COUNTER__] = get_timestamp();

int main() {
    TIMESTAMP();
    TIMESTAMP();
    return 0;
}

#define NUM_TIMESTAMPS __COUNTER__
double array[NUM_TIMESTAMPS];

Upvotes: 2

Related Questions