Reputation: 1109
From a comment to this answer: https://stackoverflow.com/a/459704/2812104
I tried to make a macro function that takes a function as argument and times it using clock()
. However I keep getting an error message saying that start
is undeclared and I can't figure it out since I do declare it earlier in the macro
(this is all on the same line in my code in case it makes a difference; I'm breaking it up in two lines here for readability):
#define timing(a): clock_t start = clock(); a; clock_t stop = clock();
printf("Elapsed: %f seconds\n", (double)(stop - start) / CLOCKS_PER_SEC);
Upvotes: 2
Views: 1783
Reputation: 755064
The immediate problem is the colon after timing(a)
— that wants a label to precede it, but you can't use labels on variable definitions, so you need to lose the colon:
#define timing(a) \
clock_t start = clock(); \
a; \
clock_t stop = clock(); \
printf("Elapsed: %f seconds\n", (double)(stop - start) / CLOCKS_PER_SEC);
You should probably also avoid polluting the function's name space. The classic way to do that is a do { … } while (0)
loop:
#define timing(a) \
do { \
clock_t start = clock(); \
a; \
clock_t stop = clock(); \
printf("Elapsed: %f seconds\n", (double)(stop - start) / CLOCKS_PER_SEC); \
} while (0)
This creates a statement block that can be used legitimately even in an unprotected if
block:
if (do_it_this_way)
timing(some_func(1, 37, 91));
else
timing(some_func(2, 41, 87));
If you use just { … }
around the macro body, this generates an error (because the semicolon after 91
means the else doesn't belong to any if
— the expansion is if (do_it_this_way) { … }; else …
).
I'm not particularly keen on this technique. I use a logically opaque type, Clock
, with support functions such as:
extern void clk_init(Clock *clk);
extern void clk_start(Clock *clk);
extern void clk_stop(Clock *clk);
extern char *clk_elapsed_ms(Clock *clk, char *buffer, size_t buflen);
extern char *clk_elapsed_us(Clock *clk, char *buffer, size_t buflen);
extern char *clk_elapsed_ns(Clock *clk, char *buffer, size_t buflen);
The calling code creates and initializes a Clock
, and can then start the clock before the loop, stop the clock after it, and at its leisure analyze the elapsed time. You can find this code on Github https://github.com/jleffler/soq/tree/master/src/libsoq in timer.c
and timer.h
. You can find examples of it being used if you search on SO with the term 'user:15168 clk_elapsed_us
' (e.g. How to wrap around a range?).
Upvotes: 5