is it possible to reset the __COUNTER__
macro at the start of a header file to make its evaluation within the header file consistent over several compile units?

- 94,151
- 12
- 143
- 190

- 397
- 3
- 14
-
1What is the `__COUNTER__` macro? Is it a compiler extension? For which compiler? Can you provide a link to the documentation for it? – Some programmer dude Apr 29 '16 at 08:00
-
2I presume you are using gcc. If you look at the [documentation](https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html) `__COUNTER__` is a helper to enable unique identifiers, therefore even if it were possible you should not reset it. – Euan Smith Apr 29 '16 at 08:05
4 Answers
How about an enum?
enum { COUNTER_BASE = __COUNTER__ };
#define LOCAL_COUNTER (__COUNTER__ - COUNTER_BASE)

- 2,118
- 1
- 19
- 25
-
2THIS works perfectly, is simple, and totally ignored by everyone! This should be the accepted answer, hands down! – Ken Kopelson Dec 29 '19 at 21:51
-
1I will just add that the formula should be: ```(__COUNTER__ - COUNTER_BASE - 1)``` – Ken Kopelson Dec 29 '19 at 21:58
-
You can set BASE
to __COUNTER__
at the top of your header file, and then use __COUNTER__ - BASE
later on.
However, do this after you've included all necessary headers, because else thee result would depend on the use of __COUNTER__
within the header guards of those nested include files.

- 173,980
- 10
- 155
- 350
-
If you would need a zero based counter BASE should be set to __COUNTER__ + 1 – rouzier Jul 06 '17 at 14:31
-
Because of preprocessor expansion, does `__COUNTER__ - BASE` count as one reference to `__COUNTER__` or two references? – jxh Jul 18 '18 at 18:34
-
I don't think this works... each reference of BASE is replaced by __COUNTER__ and thus depending on order of evaluation, the result will always be 1 or -1. – Michael Oct 11 '18 at 23:35
No, there is no way to reset that value.
Take a look at the GCC source that increments the counter:
case BT_COUNTER:
if (CPP_OPTION (pfile, directives_only) && pfile->state.in_directive)
cpp_error (pfile, CPP_DL_ERROR,
"__COUNTER__ expanded inside directive with -fdirectives-only");
number = pfile->counter++;
break;
And if you look arount this library, nowhere is the counter
modified again. It is default initialized to 0
and then incremented at every use.
Note that the pfile
, where the counter
variable resides, represents the the preprocessor input, that in this case is the current compilation unit, not the actual file.
thanks to @Michael, and by using enum you can have complete usage of __COUNTER__
as below:
"source: ESF compiler extension"
//! >>>>>>>>>>>>>>>> Counter >>>>>>>>>>>>>>>>
#pragma region Counter
/* Counter
* Ex:
* <code>
CountOn(InitSteps);
int foo(void)
{
CountIt();
...
CountIt();
...
CountIt();
...
}
Counted(InitSteps);
* </code>
* */
#define CountOn(name) enum { name ## _BASE = __COUNTER__ }; const U8 name
#define CountIt(name) (U8)(__COUNTER__ - (name ## _BASE))
#define Counted(name) const U8 name = (U8)(__COUNTER__ - (name ## _BASE) -1);
/* alias of Counter
* Ex:
* <code>
TakeSteps(InitSteps);
int foo(void)
{
AddStep();
...
AddStep();
...
AddStep();
...
}
TotalSteps(InitSteps);
* </code>
* */
#define TakeSteps(name) CountOn(name)
/* this is invalid to read, want to get value ? use 'CountIt(name)' OR 'NextStep(name)' */
#define AddStep() do { __COUNTER__; } while (0);
#define TotalSteps(name) Counted(name)
/* better use of Counter (on format print 'step, total')
* 'step' starts at 1
* Ex:
* <code>
TakeSteps(InitSteps);
int foo(void)
{
printf(StepsPRT " Initializing system clock...", NextStep(InitSteps));
...
printf(StepsPRT " Loading configurations...", NextStep(InitSteps));
...
printf(StepsPRT " Applying...", NextStep(InitSteps));
...
}
TotalSteps(InitSteps);
* </code>
* */
#define NextStep(name) CountIt(name), name
#define StepsPRT "%d of %d"
#define NextStepP StepsPRT
#pragma endregion Counter
//! <<<<<<<<<<<<<<<< .Counter <<<<<<<<<<<<<<<<

- 430
- 5
- 7