Are there C preprocessor variables?

Is there something like a preprocessor variable in C ? This may simplify my definitions.

I currently have something like this:

typedef struct mystruct {
  int val1;
  int val2;
  int val3;
  int val4;
} MYSTRUCT;

typedef struct mysuperstruct {
  MYSTRUCT *base;
  int val;
} MYSUPERSTRUCT;


#define MY_OBJECT_BEGIN(name, val1, val2, val3, val4) \
  MYSTRUCT name##Base = { val1, val2, val3, val4 }; \
  MYSUPERSTRUCT * name##Objs = {

#define MY_OBJECT_VALUE(name, val) \
  { &(name##Base), val },

#define MY_OBJECT_END() \
  NULL \
};

      

It is used as follows:

MY_OBJECT_BEGIN(obj1, 1, 2, 3, 4)
MY_OBJECT_VALUE(obj1, 5)
MY_OBJECT_VALUE(obj1, 6)
MY_OBJECT_VALUE(obj1, 7)
MY_OBJECT_END()

      

Which generates something like this:

MYSTRUCT obj1Base = { 1, 2, 3, 4 };
MYSUPERSTRUCT * obj1Objs = {
  { &(obj1Base), 5 },
  { &(obj1Base), 6 },
  { &(obj1Base), 7 },
  NULL
}

      

Obviously, reusing an object name is redundant. I would like to store the name in the MY_OBJECT_BEGIN definition for some preprocessor variable so that I can use it like this:

MY_OBJECT_BEGIN(obj1, 1, 2, 3, 4)
MY_OBJECT_VALUE(5)
MY_OBJECT_VALUE(6)
MY_OBJECT_VALUE(7)
MY_OBJECT_END()

      

Does the standard C preprocessor provide such a way?

+4


source to share


3 answers


There are no standard C preprocessor variables As Oli Charlesworth said , using X-Macros is probably your best bet if you only want to store it with standard C. If there is actually a lot of related data that touches multiple files, you will want to use a generator code like GNU autogen .



+7


source


Here's the closest general method I could think of to reuse variables in preprocessor definitions:

#include <stdio.h>

#define INIT_VALS(SIZE) unsigned int value[SIZE]; unsigned int i = 0;
#define DEFINE_VAL(NEW_VAL) value[i++] = NEW_VAL;
#define PRINT_VAL(INDEX) printf("%d\n", value[INDEX]);

int main()
{
    INIT_VALS(3)
    DEFINE_VAL(42)
    DEFINE_VAL(70)
    DEFINE_VAL(80)
    PRINT_VAL(0)
    PRINT_VAL(1)
    PRINT_VAL(2)

    // Output:
    // 42
    // 70
    // 80

    return 0;
}

      



I am not promoting this; be careful if there is no preferred solution. :)

0


source


Create an H file somewhere that clears out all possible definitions associated with your macros, for example:

#ifdef OBJECT
#    undef OBJECT
#endif

      

Then create a definition for this H file somewhere in your project:

#define CLEAR "whatever/path/you/want/clear.h"

      

Make your macros use OBJECT:

#define MY_OBJECT_BEGIN(val1, val2, val3, val4) \
  MYSTRUCT OBJECT##Base = { val1, val2, val3, val4 }; \
  MYSUPERSTRUCT * OBJECT##Objs = {

#define MY_OBJECT_VALUE(val) \
  { &(OBJECT##Base), val },

#define MY_OBJECT_END() \
  NULL \
};

      

Use it like this:

#include CLEAR
#define OBJECT obj1
MY_OBJECT_BEGIN(1, 2, 3, 4)
MY_OBJECT_VALUE(5)
MY_OBJECT_VALUE(6)
MY_OBJECT_VALUE(7)
MY_OBJECT_END()

#include CLEAR
#define OBJECT obj2
MY_OBJECT_BEGIN(1, 2, 3, 4)
MY_OBJECT_VALUE(5)
MY_OBJECT_VALUE(6)
MY_OBJECT_VALUE(7)
MY_OBJECT_END()

      

Placing open source in its own file makes it easier if in the future you may need multiple definitions for object definitions, since then you only need to add open source modifications to only one file.

I know this is not ideal, but it is the best you can do as there is no way to use the macro argument to modify the preprocessor code in any way.

0


source







All Articles