Indirect preprocessor substitution C

ideasman42

Is there a way a macro can use a value of a define passed to it, rather than the define text itself?

This is an odd example which I expected would be possible with the preprocessor.

A C file called test.c which includes itself twice to define two different functions which are called from main.

#ifndef IS_INDIRECT
#define IS_INDIRECT

/* int */
#define NUMTYPE int
#define PREFIX int_

#include "test.c"

#undef NUMTYPE
#undef PREFIX

/* short */
#define NUMTYPE float
#define PREFIX float_

#include "test.c"

#undef NUMTYPE
#undef PREFIX

#include <stdio.h>

int main(int argc, const char **argv)
{
    printf("test int %d\n", int_squared(4));
    printf("test float %f\n", float_squared(2.5));

    return 0;
}

#else

/* function body */

#define fn(prefix, id) prefix ## id

NUMTYPE fn(PREFIX, squared)(NUMTYPE val)
{
    return val * val;
}

#endif

Gives the following error:

In file included from test.c:18:0:
test.c:37:12: error: conflicting types for 'PREFIXsquared'
 NUMTYPE fn(PREFIX, squared)(NUMTYPE val)
            ^
test.c:35:24: note: in definition of macro 'fn'
 #define fn(prefix, id) prefix ## id
                        ^
In file included from test.c:9:0:
test.c:37:12: note: previous definition of 'PREFIXsquared' was here
 NUMTYPE fn(PREFIX, squared)(NUMTYPE val)
            ^
test.c:35:24: note: in definition of macro 'fn'
 #define fn(prefix, id) prefix ## id

I would like to have the macro expand PREFIX to the value it's defined as, so I get int_squared not PREFIXsquared

kuroi neko

Is it something like that you're looking for?

#define xxx(x,y)   x##y
#define CONCAT(x, y)  xxx(x, y)


#define function(type, operation, prm) type CONCAT(operation, type) (type prm)

function (int, square_, value) // int square_int (int value)
{
    return value * value;
}

The indirect use of ## allows to define a macro that uses concatenation (functionin our example). CONCAT is expanded to xxx when the macro is defined,
and resolved to x##y when the macro is invoked.

EDIT: added thanks to various contributors:

  • ## is called the token-pasting operator, or sometimes the token-concatenation operator
  • more detailed explanations on C/C++ preprocessor arguments prescan
  • an interesting blog article on the subject
  • If you pore over the incredibly obfuscated list of obscure and arbitrary reserved identifiers added by the ISO guys (you'll have to cough up about $200 to get the real spec, or resort to second hand information, or ask your favourite guru for that bit of lore), you'll eventually notice it includes those beginning with a single underscore and also with two or more, so my "_CONCAT" became "xxx".

Frankly they made such a mess of C that I would no longer dare using the language in a professional environment. I'm so glad my IT days are over.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related