kelvinwong
kelvinwong

Reputation: 113

C preprocessor #if condition

I am building some generic things in C.

Here is the code:

// main.c
#include <stdio.h>

#define T int;
#include "test.h"

int main()
{

    return 0;
}

// test.h

#define _array_is_pointer(T) (                \
    {                                         \
        T _value;                             \
        __builtin_classify_type(_value) == 5; \
    })

#ifdef T
#if _array_is_pointer(T)

struct array_s
{
    T *items;
}

void array_push(struct array_s * array, T value)
{
    // push method for pointer.
}

#else

struct array_s
{
    T *items;
}

void array_push(struct array_s * array, T value)
{
    // push method for non-pointer.
}

#endif
#endif

** edited: add more code in test.h **

I would like the preprocessor runs different code when T is pointer or non-pointer.

But I got an error token "{" is not valid in preprocessor expressions.

Is it possible to do that?

Upvotes: 0

Views: 419

Answers (3)

KamilCuk
KamilCuk

Reputation: 141010

I would like the preprocessor runs different code when T is pointer or non-pointer.

Is it possible to do that?

No, it is not possible. Preprocessor is not aware of types.

If you really want this, pass a mark if T is a pointer or not as a separate macro.

#define T  int*
#define T_IS_A_POINTER  1
#include "test.h"

Or have separate calls:

#define T  int*
#include "test_a_pointer.h"

#define T  int
#include "test_not_a_pointer.h"

Upvotes: 2

rici
rici

Reputation: 241721

The preprocessor doesn't know whether T is a pointer, because preprocessing happens before semantic analysis of the program. All the preprocessor sees are tokens; it knows that 42 is a number and take42, but that's it. The only definitions it knows about are preprocessor #defines.

Moreover, in C, functions --even builtin constant functions like sizeof and __builtin_classify_type-- cannot be evaluated by the preprocessor. The preprocessor cannot evaluate block expressions either, but there wouldn't be much point so it has no idea what a variable is and thus doesn't need declarations. The only identifier you can use in an #if preprocessor conditional are macro definitions which expand to integer constants (or entire expressions containing only arithmetic operations on integer constants).

There is the _Generic construct introduced in C11, which allows you to generate different expressions based on the type of a controlling expression. But it can only be used to generate expressions, not declarations, so it's probably not much help either.

Upvotes: 1

Priyas Paulzagade
Priyas Paulzagade

Reputation: 59

There is no issue while writing multi-line code-snippet in

#define _array_is_pointer(T) (                \
    {                                         \
        T _value;                             \
        __builtin_classify_type(_value) == 5; \
    })

But, as you have know, the first step done before passing the code to compiler is to create an Expanded source code. In this step, all the five lines woud be pasted whereever you would have written _array_is_pointer(T) and hence resulting code would have :

#if (                
        {                                         
            T _value;                             
            __builtin_classify_type(_value) == 5; 
        })

and here is a blunder. One can not write multiple lines like this in if clause, nor you could do this using {}. And hence, you got the error token "{" is not valid in preprocessor expressions.

Hence, you would have to write a single expression to in if clause preprocessor.

Upvotes: -1

Related Questions