2

I want to use a dynamic variable whose value will vary during the run time.

eg

char * aVar = "ABC";
char * bVar = "DEF";
char * cVar = "XYZ";

char *dVar = NULL;

dVar = foo1();

print dVar;

foo1 internally calls foo2, which should return the variable names (like "aVar", "bVar" or "cVar"). foo1 should return the value of said variable as named according to foo2's return value.

to get the variable name we can use (non-standard) macro:

##define GET_VAR(varname) #varname; 

... but how am I able get the value of the variable named?

4
  • 5
    Now why on earth would you be doing that in C? Commented Sep 15, 2012 at 7:48
  • @oldrinb - I was going to say something along that line of thought. Why not just return the appropriate pointer (Even though having global variables is a bad idea) Commented Sep 15, 2012 at 7:54
  • Or pass an out param to functions foo1() and foo2() respectively which simply put the value in the param after completing processing Commented Sep 15, 2012 at 7:59
  • 1
    @oldrinb: personally I don't seem to find myself doing it even in languages that support it. The languages that allow it mostly seem to have easy-to-use associative containers. Not by coincidence ;-) Commented Sep 15, 2012 at 8:26

4 Answers 4

4

The simple answer here is that this is not possible in C.

The longer answer is that this requires introspection and dynamic features in a language, which is something that is generally only seen in scripting languages such as Python. And even there doing something like this is not encouraged.

I suggest that you reconsider the problem you are trying to solve and check if there might not be a better method to approach it. Perhaps using an array, map or hash table might be an alternative approach that works for you.

Sign up to request clarification or add additional context in comments.

3 Comments

Although it's not advisable, you can do dynamic loading - see my answer.
That's certainly an interesting approach. I doubt it is very portable though, and it might break if a compiler or linker does some unexpected optimisation. Still - bonuspoints for coming up with this :)
it should be portable across POSICes.
2

C is not a dynamic language - you can't really do this. You'd just better use some kind of data structure, such as a dictionary (key-value store, associative array, however you call it) for this purpose.

Well, unless... unless you have a POSIX-conformant system and you like evil dynamic loading.

#include <dlfcn.h>
#include <stdio.h>

int globalVarOne = 1;
int globalVarTwo = 2;
int globalVarThree = 3;

int getValueOfVariableNamed(const char *name)
{
    void *ptr = dlsym(RTLD_SELF, name);
    return *(int *)ptr;
}

int main()
{
    printf("globalVarOne = %d\n", getValueOfVariableNamed("globalVarOne"));
    // etc.
}

Prints:

globalVarOne = 1

Note that this only works for global variables.

Edit: as @oldrinb pointed out, you can also do this on Windows if you substitute void *ptr = GetProcAddress(GetModuleHandle(NULL), name); instead of void *ptr = dlsym(RTLD_SELF, name);.

2 Comments

Equivalent for Windows: GetProcAddress(GetModuleHandle(NULL), name)
Handy thing this dlsym() is.
1

You can't do it directly in C.

You can do something like this however:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct Binding
{
  int* pIntVar;
  const char* IntVarName;
  struct Binding* pNext;
} Binding;

Binding* Bindings = NULL;

void BindVar(const char* IntVarName, int* pIntVar)
{
  Binding* b;
  if ((b = malloc(sizeof(Binding))) != NULL)
  {
    b->IntVarName = IntVarName;
    b->pIntVar = pIntVar;
    b->pNext = NULL;
    if (Bindings == NULL)
    {
      Bindings = b;
    }
    else
    {
      Binding* bs = Bindings;
      while (bs->pNext != NULL)
      {
        bs = bs->pNext;
      }
      bs->pNext = b;
    }
  }
  else
  {
    fprintf(stderr, "malloc() failed\n");
    exit(-1);
  }
}

int* GetVarPtr(const char* IntVarName)
{
  Binding* bs = Bindings;
  while (bs != NULL)
  {
    if (!strcmp(bs->IntVarName, IntVarName))
    {
      return bs->pIntVar;
    }
    bs = bs->pNext;
  }
  fprintf(stderr, "variable \"%s\" not bound yet!\n", IntVarName);
  exit(-1);
}

int main(void)
{
  int ABC = 111, DEF = 222, XYZ = 333;
  const char* varName = NULL;

  BindVar("ABC", &ABC);
  BindVar("DEF", &DEF);
  BindVar("XYZ", &XYZ);

  printf("variable \"%s\" = %d\n", "ABC", *GetVarPtr("ABC"));
  printf("variable \"%s\" = %d\n", "DEF", *GetVarPtr("DEF"));
  printf("variable \"%s\" = %d\n", "XYZ", *GetVarPtr("XYZ"));

  // Pick a variable randomly by name

  switch (rand() % 3)
  {
  case 0: varName = "ABC"; break;
  case 1: varName = "DEF"; break;
  case 2: varName = "XYZ"; break;
  }

  printf("variable \"%s\" (selected randomly) = %d\n", varName, *GetVarPtr(varName));

  return 0;
}

Output (ideone):

variable "ABC" = 111
variable "DEF" = 222
variable "XYZ" = 333
variable "DEF" (selected randomly) = 222

Since GetVarPtr() returns a pointer to a variable, you can not only get the variable's value, but also set it.

You can even hide the pointer thing behind a macro:

#define VARIABLE(NAME) (*GetVarPtr(NAME))

In this way you can do things like this (ideone):

VARIABLE("ABC") = 1;
VARIABLE("DEF") = 2;
VARIABLE("XYZ") = 3;

printf("variable \"%s\" = %d\n", "ABC", VARIABLE("ABC"));
printf("variable \"%s\" = %d\n", "DEF", VARIABLE("DEF"));
printf("variable \"%s\" = %d\n", "XYZ", VARIABLE("XYZ"));

Comments

0

You can't use macros during runtime.

You should use an array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.