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?
CodePudding user response:
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 #define
s.
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.
CodePudding user response:
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.