Home > Software engineering >  How to handle defines in C with pre processor instructions (gTest background)?
How to handle defines in C with pre processor instructions (gTest background)?

Time:06-10

I am used to handle defines like the following code snipped shows. The paramA is initialized with 1 (edit: defined as 1) and can be used in the code. So far so good...

#define paramA 1

int main(void)
{
  int varTest1 = 0;

  if(paramA < 2)
  {
    varTest1 = 1;
  }
  else
  {
    varTest1 = 2;
  }
  return 0;
}

Now I'm dealing with a code where I receive the following define:

#define ALGO_FEATURE ALGO_FEATURE_A

First question: What kind of type is "ALGO_FEATURE_A" ? What does here happen? Is it some kind of text define? Or is this even legal? It actually builds and seams to be valid from my point of view.

My goal is to react (I'm doing unittests with gTest) on different algo features with different tests. So if "ALGO_FEATURE" is "ALGO_FEATURE_A" I would like to call different tests than in case it is "ALGO_FEATURE_B".

Current approach looks like this (according to the first code snipped). But it does not work... No matter which one of the following versions. The result is always that the if condition is true.

First approach (while debugging it always run into the first option, even if the if conditions are switched.

#if (ALGO_FEATURE == ALGO_FEATURE_B)      
  EXPECT_TRUE(FALSE); // this line is always run, even if ALGO_FEATURE is not ALGO_FEATURE_B
#elif (ALGO_FEATURE == ALGO_FEATURE_A)
  EXPECT_TRUE(TRUE); // this line is never reached even if it should be true
#endif

How can I adapt this approach ?

Thanks for your time !

CodePudding user response:

paramA is initialized with 1

No, paramA is replaced by the source text 1 wherever it appears.

What kind of type is ALGO_FEATURE_A

It isn't a type. Presumably it is itself a #define, so ALGO_FEATURE will be the same source text.

I would guess that both ALGO_FEATURE_A and ALGO_FEATURE_B are defined to 1, so your tests are equivalent to

#if (1 == 1)      
  EXPECT_TRUE(FALSE); // this line is always run, even if ALGO_FEATURE is not ALGO_FEATURE_B
#elif (1 == 1)
  EXPECT_TRUE(TRUE); // this line is never reached even if it should be true
#endif

You can't distinguish between something #defined to be one or the other of those if they are the same value. If there is an #if around the definition of ALGO_FEATURE, then you can use that, or you could #define IS_ALGO_FEATURE_A, with the test

#if defined (IS_ALGO_FEATURE_B)      
  EXPECT_TRUE(FALSE);
#elif defined (IS_ALGO_FEATURE_A)
  EXPECT_TRUE(TRUE);
#endif

CodePudding user response:

The C preprocessor does verbatim substitutions.

For instance

#define A B   
if (A == B)

generates the code

if (B == B)

whatever that means.

If your purpose is variant code generation, you could use a construct like

// Available versions
#define BLUE  1
#define GREEN 2

// Desired version
#define VERSION BLUE // Or GREEN

#if VERSION == BLUE
// Blue code
#else
// Green code
#endif

This translates to

#if 1 == 1
// Blue code
#else
// Green code
#endif

so just

// Blue code

Extra remark:

if (VERSION == BLUE)
{
  // Blue code
}
else
{
  // Green code
}

Would probably have the same effect on optimized code, by dead branch elimination. (I am not recommending such a practice.)

CodePudding user response:

How to handle defines in C with pre processor instructions

A possibility is to use some other program to generate C code, or to generate test cases (or various test inputs).

Consider using GPP or GNU m4 to generate C code.

Perhaps you want to use GNU autoconf.

You certainly could use GNU make to build your program with partly generated C code.

Take inspiration from Qt. It does generate C code (in its moc) and is an open source framework.

Maybe consider using POCO.

#define ALGO_FEATURE ALGO_FEATURE_A

The ALGO_FEATURE_A might be provided elsewhere, e.g. if you compile with GCC invoked as gcc -Wall -DALGO_FEATURE_A

And your code could latter use preprocessor conditions like

#ifdef ALGO_FEATURE_A
/// some code
#endif

Read documentation of GNU cpp and of GCC.

  • Related