user13721385
user13721385

Reputation:

Typechecking in C preprocessor

I was hoping to implement optional arguments in c by using macros to set a function based on the variable type.

#define dostuff(BOOL) dostuffwithbool(BOOL)
#define dostuff(INT) dostuffwithint(INT)

Is this kind of thing possible at all? (even though I know it probably isn't). I'd accept any answer no matter how long or hacky.

Upvotes: 1

Views: 582

Answers (2)

HElectronix
HElectronix

Reputation: 61

You can't do it with just the macro itself, because macro is a placeholder (for the preprocessor) and not a function (subroutine).

The preprocessor replaces all occurrences of a macro with the code you define at the macro's definition. It's the same with numeric defines like #define PI 3.141592654. Here, PI is not a variable. Instead, every occurrence of PI in the code will be replaced with 3.141592654. Same counts for the macros.

So for example this code with a simple comparison macro:

#include <stdio.h>

#define EQUALS(a, b) (a == b ? 1 : 0)

int main()
{
    char nZero = 0;
    char nOne = 1;
    printf("0 is 0: %d\n", EQUALS(nZero, nZero));
    printf("0 is 1: %d\n", EQUALS(nZero, nOne));
    return 0;
}

Will be expanded to the folowing code by the preprocessor:

int main()
{
    char nZero = 0;
    char nOne = 1;
    printf("0 is 0: %d\n", (nZero == nZero ? 1 : 0));
    printf("0 is 1: %d\n", (nZero == nOne ? 1 : 0));
    return 0;
}

Note: Be careful with macros, because they will be expanded exactly the way you write them in their definition. So for example it is good practice to place brackets around calculations, since something like this:

#define ADD(a, b) a + b
int x = a * ADD(b, c);

will be expanded to this:

int x = a * b + c;

and not this:

int x = a * (b + c);

Upvotes: 1

tstanisl
tstanisl

Reputation: 14166

The preprocessor itself is not capable of processing C types because macros are expanded after tokenization of program but the before syntactical constructs of C language are parsed.

Depending on your application you can use _Generic available from C11. It is basically switch-case over types.

#define dostuff(val)                    \
  _Generic((val), bool: dostuffwithbool \
                , int:  dostuffwithint) (val)

Note that this solution will not work if dostuffwithbool/dostuffwithint were function-like macros. The macros would not be expanded due to a lack of ( following a macro.

Upvotes: 2

Related Questions