Luca_Previ0o
Luca_Previ0o

Reputation: 39

Is there a way to use variable's data in C?

I'm trying to create something like a library. I found out that, using #define macros, you can pretty much do anything you want with your code, and I tried to chain some of them in some crazy way to make some cool stuff happen.

For that reason, I'm trying to create a tool that uses a function-like macro, in which you pass a type name (like int or float), and it creates some typedef struct things and related functions, in order to make a new data type List(type).

The idea is, you only need to specify the type of the list and the name of the new list, as you would declare any variable, and it already knows which functions you have to work with it:

/* this function is not present in the code, but */
/* I call it in the .h file to make sure that it's */
/* possible to have an existent List(float) type. I */
/* added this, because I want to work i the future on */
/* the possibility to have a user-defined type for which */
/* you can build a List(custom_type) variable */
declare_new_type(float);

List(float) list;

main() {

  /*do stuff with the list, */
  /* using some functions defined in the library */
  /* along with the List(float) type */
  return 0;
}

When I wrote the library, I put in a macro (that is not to be called by the programmer who uses the library itself, but it's called by me in order to declare for which types the type List(type) exists) that defines the data type and a bunch of functions that work with variables of the same type.
All of that is done with a lot of other #ifndef and #define macros, all of which pass to one another the same parameter typename, that is the one I pass myself when I call declare_new_type(type) (to put it in other words, the parameter value is literally type).
In this way, all the other expanded macros know the actual content in the typename parameter, and they are able to create a lot of function with variable types in return and names that depend from that same parameter using the ## macro expansion tool. For example, the begin(...) function that one of these macros defines is defined as following:

/* when I call begin(float) in the main code, */
/* it just makes a call to this function, and not to */
/* this code snippet for the definition */

#define begin(typename) typename##List fBegin##typename() { \
\
typename##List e=(typename##List)malloc(sizeof(typename##Item)); \
e->v=0; \
e->next=NULL; \
return e; \
}

For this one, I have no problems, because I have to pass another time the typename parameter when I call the function (to avoid type mismatch in the declaration of the data type, and the data that it works on), and for that reason it calls exactly the fBeginfloat() function that is defined when I call the declare_new_type(type) function.
In other cases, however, I wanted the function to have only the List(type) variable as parameter (and some other needed parameters to work with it), but not the actual type that it works on, and there the real problem comes out.

For some reason (probably, me not knowing much about C compiling and high-level programming), I'm not able to extract the type of a variable and pass it to any other function. It seems that even operators like sizeof(variable) or typeof(variable) are not able to pass what I want them to pass as parameters, when they get called as function parameters them selves.
I tried using # macro operators, blocks of code, anything to make it happen, and I just don't seem able to do it.

Now, I wonder if it's really possible to make something like this happen: is it possible to pass a variable to a #define macro, or even to another defined function, and have it to get the variable type, in order to pass it as parameter to another macro or function? I hope you understood the problem, and will help me in some way. Thanks!

Upvotes: 0

Views: 130

Answers (1)

rici
rici

Reputation: 241671

An important insight into the C preprocessor (which handles macros) is that it knows absolutely nothing about the semantics of the program. Nothing. For the preprocessor, the input is just a sequence of tokens, and all it does is rearrange those tokens according to some rules.

So, it doesn't know what a type is, or what a variable is, or what the type of a variable might be, and certainly not what the value of a variable might be.

(It can do arithmetic in the context of an #if directive. But it is still only working with tokens, not with C variables or expressions or whatever. An identifier in an #if will be expanded (not evaluated) if it has previously been #defined; otherwise it is replaced with 0 for the conditional evaluation. And there is no way of saving the result of an arithmetic expression; #if is only a conditional.)


So, to address the question in the last paragraph of your post:

typeof() is a very recent addition to C, although it is implemented as an extension in several C compilers. The result of typeof is a type, which is an internal compiler data object. You cannot convert a type to a string, and it is not a value which exists at runtime, so it makes no sense to try to pass it as an argument to a function. In C, types occupy the very short time after the preprocessor and before code generation.

However, you can use typeof to define other types, and you can name those types using typedef. (Remember that typedef is just a type alias, not a new type. Two typedefd names which alias the same type are the same type, unlike two anonymous struct declarations with the same members.)

Upvotes: 2

Related Questions