Reputation: 15
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?
Upvotes: 1
Views: 1609
Reputation: 16406
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
Upvotes: 6
Reputation: 2814
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");
}
Upvotes: 0
Reputation: 171127
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()
.
Upvotes: 4
Reputation: 153909
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.
Upvotes: 1
Reputation: 62472
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;
}
Upvotes: 1