简体   繁体   中英

Pre-processor #if doesn't work

I'm trying to write a somehow-generic printArray function in C , which I will able to run with several programs, each with a different type of array. I did this:

#define TYPE int /* or char or double*/

void printArray(TYPE *a, int size){
    for (int i=0; i<size; i++){
#if TYPE == int
        printf("%d ", a[i]);
#elif TYPE == char
        printf("%c ", a[i]);
#elif TYPE == double
        printf("%f ", a[i]);
#endif
    }
    printf("\n");
}

I have tried running it, but no matter what TYPE is defined to be, the first #if always checks in, meaning - if the if's are written:

#if TYPE == int
        printf("int");
#elif TYPE == char
        printf("char");
#elif TYPE == double
        printf("double");
#endif

then it will print "int", even if TYPE is defined to be char, and if

#if TYPE == char
        printf("char");
#elif TYPE == int 
        printf("int");
#elif TYPE == double
        printf("double");
#endif

then it will print "char", even if TYPE is defined to be int, etc.

ideas?

Preprocessor #if evaluates integer expressions. You're trying to treat == as if it were comparing tokens. Since int, char, double, etc. are not defined as preprocessor variables, they all evaluate as 0.

You could do

#define TYPE int
#define FMT "%d"

void printArray(TYPE *a, int size){
    for (int i=0; i<size; i++)
        printf(FMT " ", a[i]);

    printf("\n");
}

Much simpler, and it works.

If you want to only have to specify the TYPE, you could do something like

#define FMT_int "%d"
#define FMT_char "%c"
#define FMT_double "%f"
#define FMT PPCAT(FMT_, TYPE)

where PPCAT is defined in my answer to C/C++ Macro string concatenation

The C and C++ preprocessor can only work with numbers (numeric literals, to be exact). In expressions, any words it doesn't recognize (after all macro expansion) are treated as a 0 .

You'd need to do something like this:

#define TYPE_int 0
#define TYPE_char 1
#define TYPE_double 2

#define TYPE_USED TYPE_int

#if TYPE_USED == TYPE_int
typedef int TYPE;
#elif TYPE_USED == TYPE_char
typedef char TYPE;
#elif TYPE_USED == TYPE_double
typedef double TYPE;
#endif

void printArray(TYPE *a, int size){
    for (int i=0; i<size; i++){
#if TYPE_USED == TYPE_int
        printf("%d ", a[i]);
#elif TYPE_USED == TYPE_char
        printf("%c ", a[i]);
#elif TYPE_USED == TYPE_double
        printf("%f ", a[i]);
#endif
    }
    printf("\n");
}

You could use boost.preprocessor to do some metaprogramming magic with preprocessor loops instead of listing all the values manually.

Of course, the above code applies to C. If you're using C++, use a template instead of macro hacks and std::cout instead of printf() .

You should avoid the pre-processor wherever possible, and this is a classic example of when to avoid it! If you need to write code that depends on type then you can use either template, inheritance or polymorphism for this.

In this case you can rewrite printArray as a template function:

template<class T>
void printArray(T *data, int count)
{
  for(int i=0; i<count; i++)
  {
    cout << data[i] << " ";
  }

  cout << endl;
}

Preprocessor evaluation is more or less like C++ evaluation. It is numeric (despite the fact that the preprocessor works with text). Any preprocessor symbol which remains after macro expansion is replaced by 0 , and C++ keywords are still symbols in the preprocessor. (There is a special exception for the preprocessor symbol true , which expands to 1 .) So in the end, all of your comparisons come out to 0 == 0 , which is always true.

http://msdn.microsoft.com/en-us/library/ew2hz0yd(v=VS.80).aspx

The constant-expression is an integer constant expression with some additional restrictions.

It seems u can't compare strings. Try the following:

#define TYPE_int /* put this too */
#define TYPE int /* or char or double*/
void printArray(TYPE *a, int size){
    for (int i=0; i<size; i++){
#ifdef TYPE_int
        printf("%d ", a[i]);
#elif defined TYPE_char
        printf("%c ", a[i]);
#elif defined TYPE_double
        printf("%f ", a[i]);
#endif
    }
    printf("\n");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM