Alex Rivera | Logout

How to generate random variable names in C++ using macros?

Asked 2009-07-04T13:16:54.077
31

I'm creating a macro in C++ that declares a variable and assigns some value to it. Depending on how the macro is used, the second occurrence of the macro can override the value of the first variable. For instance:

#define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();

The other motivation to use that is to avoid selecting certain name to the variable so that it be the same as a name eventually chosen by the developer using the macro.

Is there a way to generate random variable names inside a macro in C++?

-- Edit --

I mean unique but also random once I can use my macro twice in a block and in this case it will generate something like:

int unique_variable_name;
...
int unique_variable_name;

In this case, to be unique both variable names have to be random generated.

Edit
Report

2 Answers

51

Try the following:

// One level of macro indirection is required in order to resolve __COUNTER__,
// and get varname1 instead of varname__COUNTER__.
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define CONCAT_INNER(a, b) a ## b

#define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)

void main() {
  int UNIQUE_NAME(foo) = 123;  // int foo0 = 123;
  std::cout << foo0;           // prints "123"
}

__COUNTER__ may have portability issues. If this is a problem, you can use __LINE__ instead and as long as you aren't calling the macro more than once per line or sharing the names across compilation units, you will be just fine.

answered 2013-07-12T22:06:06.147
2

I needed something similar for a case where I didn't have any profiling tools, but I wanted to count how many threads were inside a particular block of code as well as the amount of time (ticks) spent in that block of code by each thread, In this case every block needed a unique static variable accessible to all threads, and I needed to later reference that variable to incr (I used a logging API rather than printf in the actual code, but this works as well). At first I thought I was very clever by doing the following:

#define PROF_START { \
    static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
    clock_t start, end; \
    start = times(0); \
    (*ptc)++;

But then I realized this is just silly and the C compiler will simply do this for you, as long as each "static" declaration is its own block:

#include <stdio.h>
#include <sys/times.h>

#define PROF_START { \
    static int entry_count = 0; \
    clock_t start, end; \
    start = times(0); \
    entry_count++;


#define PROF_END \
    end = times(0); \
    printf("[%s:%d] TIMER: %ld:%d\n" , __FUNCTION__, __LINE__, end-start, entry_count); \
    entry_count--; \
    }

Note the open/close brackets in each macro. This isn't strictly thread-safe, but for my profiling purposes I could assume the incr and decr operations were atomic. Here's a recursion sample which uses the macros

#define ITEM_COUNT 5

struct node {
   int data;
   struct node *next;
 };

revsort(struct node **head)
{
  struct node *current = *head;
  struct node *next_item;

  while (current->next)
  {
PROF_START
    next_item = current->next;
    current->next = next_item->next;
    next_item->next = *head;
    *head = next_item;
PROF_END
  }
}

rrevsort(struct node **head)
{
  struct node *current = *head;
  struct node *next_item 
answered 2012-05-03T02:35:18.063

Your Answer