jruiz
jruiz

Reputation: 71

C macro returning type of variable

Could it be possible to create a macro function whose returned value be one of the predefined c variable data types? Something like:

#include <stdio.h>
#define IND_I_ 0
#define IND_F_ 1
#define INT_FORMAT_ "%i"
#define FLOAT_FORMAT_ "%f"
// (Of course the following macros do not make the desired jobs)
// FORMAT_ macro would be used for the variable format:
#define FORMAT_( ind_ )( (ind_) == IND_I_ ? FOR_INT_ : FOR_FLOAT_ )
// VAR_TYPE_ macro would be used for 
// defining variable types and for the casting of variables:
#define VAR_TYPE_( ind_ ) ( (ind_) == IND_I_ ? int : float )

int main( void )
{
  VAR_TYPE_( IND_I_ ) first_var = 123; //here I want: int first_var = 123;
  VAR_TYPE_( IND_F_ ) second_var = 345.789;
  //Instead of:
  //printf( "int variable = " "%i" "\n", first_var );
  //I would use:
  printf( "int variable = " FORMAT_(IND_I_) "\n", first_var );
  printf( "float variable = " FORMAT_(IND_F_) "\n", second_var );
  printf( "truncated real variable = "  INT_FORMAT_ "\n", (VAR_TYPE_(IND_I_))second_var );
  return 0;
}

Upvotes: 1

Views: 2407

Answers (3)

Galaxy
Galaxy

Reputation: 1279

Macros r just literal replacing,so you can not do it this way. Use c++ 11 / 14, auto type and outstream handle will fit.

Upvotes: 1

Koshinae
Koshinae

Reputation: 2320

The short answer is: no.

What do you want to achieve?
Why do you need flexible typing in C? Maybe you should move on to Java or Python then.

In your example, you already have type information, so using macros to substitute type-specific string literals are overkill.

If you want to control the types of the variables from the outside, which I strongly oppose, you can set up macro substitutes and inject them through a header or directly specifying them on the compiler's command line.

Example for demonstration (please don't do this at home):

#include <stdio.h>
#include <stdlib.h>
/* // eg.
#define TEH_TYPE double
#define TEH_TYPE_FMT "%f"
#define TEH_TYPE_ATO atof
*/
// Either, or see command line below.
/*
#define TEH_TYPE int
#define TEH_TYPE_FMT "%d"
#define TEH_TYPE_ATO atoi
*/

int main(int argc, char **argv) {
    TEH_TYPE v;
    if(argc > 1)
    {
        v = TEH_TYPE_ATO(argv[1]);
        printf("So your thingie is " TEH_TYPE_FMT "\n", v);
    }
    return 0;
}

You can then compile it as gcc -DTEH_TYPE=int -DTEH_TYPE_FMT='"%d"' -DTEH_TYPE_ATO=atoi main.c -o main.

But again, please don't. I am ashamed of writing this down.

Upvotes: 0

zwol
zwol

Reputation: 140559

Sorry, this is not possible in the C family. (It is possible in languages with a more powerful macro system, such as Common Lisp and Rust.)

The only thing a macro can do is textual replacement. So your

#define VAR_TYPE_( ind_ ) ( (ind_) == IND_I_ ? int : float )
#define IND_I_ 0
VAR_TYPE_( IND_I_ ) first_var = 123;

expands to

( (0) == 0 ) ? int : float ) first_var = 123;

which is a syntax error. There is no way to make it evaluate that ?: expression.

There is a thing you could do that would make it work whenever the argument to VAR_TYPE_ expanded to a literal zero, one, etc.:

#define VAR_TYPE_(ind_) VAR_TYPE__(ind_)
#define VAR_TYPE__(ind_) VAR_TYPE__##ind_
typedef int VAR_TYPE__0;
typedef float VAR_TYPE__1;
// etc

... but if you're doing this at all, you probably want to allow ind_ to be an arbitrary integer constant expression and that won't work. You would get things like

VAR_TYPE_sizeof(int)==4?0:2

in the expansion and you'd be back to the syntax errors.

(Psst: Every time you put spaces on the inside of your parentheses, God kills a kitten.)

Upvotes: 3

Related Questions