Reputation: 25
Why are certain strings replaced and others not replaced with #define?
$ cat test.c
#define X_ REPLACED
int main() {
X_x();
X_();
return 0;
}
$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
int main() {
X_x();
REPLACED();
return 0;
}
Above X_();
is replaced but X_x();
is not. What are the rules? I can't find any info on this anywhere despite a long investigation.
Reason I'm looking at this is: I want to link to an FFT library (FFTW) whose routine names start with fftwf_, fftw_, fftwl_ or fftwq_ depending on whether single, double, long double or quadratic precision is in use.
(gcc version: 4.4.3)
Upvotes: 0
Views: 206
Reputation: 25
Thank you that is exactly what I wanted. I've edited a bit your solution as follow:
#ifdef single
#define myType fftwf_
#else
#ifdef double
#define myType fftw_
#endif
#endif
#define CONCAT(x, y) x##y
#define FFTW_FUNC(fft_type, fft_func) CONCAT(fft_type, fft_func)
int main() {
//
FFTW_FUNC(myType, func)(args);
//
}
The above gives:
$ gcc -E -Ddouble test.c; gcc -E -Dsingle test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 12 "test.c"
int main() {
fftw_func(args);
}
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 12 "test.c"
int main() {
fftwf_func(args);
}
Upvotes: 0
Reputation: 3322
Because the preprocessor works on a token-by-token basis, and X_x
counts as one token, hence it is ignored by the #define
. If you need X_x
to become REPLACEDx()
, use sed or any other regexer to preprocess the code.
Because macros are dumb, argument introspection is impossible, so you can't really do `#define fft_func(mytype If you want to do that effect without regexes, use
#define CONCAT2(x, y) x##y
#define CONCAT(x, y) CONCAT2(x, y)
#define FFTW_FUNC(fft_type, fft_func) CONCAT(CONCAT(CONCAT(fftw, fft_type), _), fft_func)
int main() {
// ...
FFTW_FUNC(type, func)(args);
// ...
}
For fft types:
#define FFTWT_FLOAT f
#define FFTWT_DOUBLE
#define FFTWT_LONG_DOUBLE l
#define FFTWT_QUAD_PRECISION q
Upvotes: 3