Is there any way we can form and execute a statement at runtime in C?
Printable View
Is there any way we can form and execute a statement at runtime in C?
Well, yes and no. You can't form a C expression and run it, but you could generate code at runtime - there is also no standard way of doing that, it changes both with processor architecture and OS architecture how you go about this.
What are you actually trying to do? As in, do you have a particular problem you are trying to solve, and if so, can you explain what the problem is?
--
Mats
There are three integer variables x1, x2 and x3 having values 1,2 and 3 respectively. Another fourth array variable x contains either x1, x2 or x3. I want to print the value of the variable which is the value of x. e.g. if x contains x2, I want to display 2. (Of course this is a simplification of a bigger program).
Sounds like all you need is a pointer to the right variable [somehow you must know which variable you want printed somewhere, right?]
--
Mats
Yes.
So I take it that solved the problem?
--
Mats
Not really! I was thinking of this in a larger perspective. For this small scale problem, we can use if or swich statement or a program of the following kind. But I wanted to know whether there is any other technique through which we can form a statement and execute it at runtime.
Code:#define GET_VAL(x) (strcmp(x, "x1") == 0) ? x1 : ( \
(strcmp(x, "x2") == 0) ? x2 : ( \
(strcmp(x, "x3") == 0) ? x3 : 0))
main()
{
int x1 = 1;
int x2 = 2;
int x3 = 3;
char x[20];
printf("Enter value of x ");
scanf("%s", x);
printf("Value is %d\n", GET_VAL(x));
}
Thanks
You could use an array of ints instead of 3 different ints, then just take an index number instead of a variable name from scanf(). Or if the user really feels the need to put x before the number, just strip off the x from the input, convert the rest to an int and use it as the array index.
That also will work. But my original point is different. I wanted to know whether there is any other technique through which we can form a statement and execute it at runtime.
Thanks
Soham
Sounds like what you want to do is dynamically create/reference variable names.
But I am pretty sure that is impossible.
edit: or maybe you can with macros which I have little experience with
So do you want the user to be able to enter something like this:
and have your program compile and run that code, or do you just want simple arithmetic statements?Code:sprintf( str, "a = %d", i );
If you want to write your own C shell, it'll probably be pretty damned hard & time consuming.
I want to execute it also. I think it is not that easy. I wanted something like Dynamic SQL from Oracle.
ANyways, thanks.
You could generate temp .c file and compile/execute it... or maybe there's some "library" for compiling code...
EDIT: or compile into shared library, and dlopen() it in current context...
So, are you writing something like a calculator/expression parser/spreadsheet application?
If so, you probably should consider implementing a "variable storage".
If you want a way to use/get variables out of your application for debug purposes or some such, you could add some code to store a name and variable, e.g.
--Code:#define ADD_VAR(t, x) add_var(#t, #x, &x,)
#define REMOVE_VAR(x) remove_var(#x)
void add_var(const char *type, const char *name, void *addr)
{
// Store type, name and addr in some sort of stack/list/array/etc.
}
void remove_var(const char *name)
{
// remove the last added variable of that name.
}
const char *get_fmt(const char *type)
{
const static struct {
char *type;
char *fmt;
} table[] =
{
{ "int", "%d" },
{ "char *", "%s" },
{ NULL, NULL }
};
int i;
for(i = 0; table[i].type; i++)
{
if(strcmp(type, table[i].type) == 0)
return table[i].fmt;
}
return NULL;
}
void print_var(const char *name)
{
// Find name in list.
if (found)
{
const char *fmt = getfmt(found->type);
char buffer[100];
if (!fmt) printf("Unknown format %s\n", found->type);
else
{
sprintf(buffer, "%s = %s\n", name, fmt);
printf(buffer, *found->addr);
}
}
else
{
printf("Could not find variable\n");
}
}
int main()
{
int x = 1;
int y = 7;
char *str = "foo";
char *name;
ADD_VAR(int, x);
ADD_VAR(int, y);
ADD_VAR(char *, str);
scanf("%s", name);
print_var(name);
REMOVE_VAR(str);
REMOVE_VAR(y);
REMOVE_VAR(x);
}
Mats
Thanks matsp. Very good idea.
I have made some syntax changes to your program and it works very good. Really a good idea.
Code:#include <stdio.h>
#include <stdlib.h>
#define ADD_VAR(t, x) add_var(#t, #x, &x)
#define REMOVE_VAR(x) remove_var(#x)
int total = 0;
typedef struct {
char *type_list;
char *name_list;
void *addr_list;
} store_list;
store_list *store = NULL;
void add_var(const char *type, const char *name, void *addr)
{
total++;
store = realloc(store, total * sizeof(store_list));
/* Store type, name and addr in some sort of stack/list/array/etc. */
store[total-1].type_list = type;
store[total-1].name_list = name;
store[total-1].addr_list = (int *) addr;
}
void remove_var(const char *name)
{
/* // remove the last added variable of that name. */
}
const char *get_fmt(const char *type)
{
const static struct {
char *type;
char *fmt;
} table[] =
{
{ "int", "%d" },
{ "char *", "%s" },
{ NULL, NULL }
};
int i;
for(i = 0; table[i].type; i++)
{
if(strcmp(type, table[i].type) == 0)
return table[i].fmt;
}
return NULL;
}
void print_var(const char *name)
{
int i = 0;
store_list *found;
found = NULL;
/* Find name in list. */
for (i=0; i<total; i++)
{
if (strcmp(store[i].name_list, name) == 0)
{
found = &store[i];
}
}
if (found)
{
const char *fmt = get_fmt(found->type_list);
char buffer[100];
if (!fmt)
printf("Unknown format %s\n", found->type_list);
else
{
sprintf(buffer, "%s = %s\n", name, fmt);
if (strcmp(fmt, "%d") == 0)
{
printf(buffer, *(int *)found->addr_list);
}
else if (strcmp(fmt, "%s") == 0)
{
printf(buffer, (char *)found->addr_list);
}
}
}
else
{
printf("Could not find variable\n");
}
}
int main()
{
int x = 8;
int y = 7;
char str[20] = "foo";
char name[20];;
ADD_VAR(char *, str);
ADD_VAR(int, x);
ADD_VAR(int, y);
scanf("%s", name);
print_var(name);
/*
REMOVE_VAR(str);
REMOVE_VAR(y);
REMOVE_VAR(x);
*/
}
I suppose I should have pointed out that I just typed it in, with no compilation/checking - it was meant to show the concept, not really be a complete solution...
And calling realloc every time is probably not a very clever way to make sure you have enough memory for the variables... Keep a "high water mark", and only call realloc if you go over that limit.
--
Mats
You are right. I know you had just pointed out the general structire of the program. I just completed it for the benefit of others too. (without remove).
I have used realloc so that only needed space is allocated (as against array). I could have used linked list, but I wanted some quick testing.
This is just a prototype program.
Thanks for a very good idea.