Thierry Fernand
Thierry Fernand

Reputation: 25

C preprocessing

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

Answers (2)

Thierry Fernand
Thierry Fernand

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

moshbear
moshbear

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

Related Questions