preprocessor trick

L

Lola

Hi,

I am trying the folowing preprocessor trick with gcc but it doesn't
seem to work (worked with all the compilers I have used so far):

#ifdef GLOBAL_VARS
#define EXT
#define EQ =
#else
#define EXT extern
#define EQ ;##/##/
#endif

I get the error:

In file included from src/verilog.cpp:16:
../include/verilog.h:35:1: pasting ";" and "/" does not give a valid
preprocessing token
../include/verilog.h:35:1: pasting "/" and "/" does not give a valid
preprocessing token
In file included from src/verilog.cpp:16:
../include/verilog.h:35: error: expected unqualified-id before '/'
token

any ideas?
lola
 
B

Ben Bacarisse

Lola said:
I am trying the folowing preprocessor trick with gcc but it doesn't
seem to work (worked with all the compilers I have used so far):

As a general rule, I am wary of anything that can be called a
"preprocessor trick". Often, the effect is to obfuscate the code so you
need to be sure that they pay their way, so to speak.
#ifdef GLOBAL_VARS
#define EXT
#define EQ =
#else
#define EXT extern
#define EQ ;##/##/
#endif

I get the error:

In file included from src/verilog.cpp:16:

From the file name it looks like you may be using C++. You should know
that there are differences between the two preprocessors and this may
matter. In fact, the way I'd do what I think you are trying to do
relies on one of these differences.
./include/verilog.h:35:1: pasting ";" and "/" does not give a valid
preprocessing token

The error message is accurate. Presumably you know what ## does in a
macro body -- it joins two tokens into one -- and the message is
reporting that ;/ is not a valid token in C. I'd guess the first ## is
simply not meant to be there.
./include/verilog.h:35:1: pasting "/" and "/" does not give a valid
preprocessing token

This one, though accurate, is not so helpful. Comments are treated as
white space so // is not, in fact, a valid preprocessing token. What's
more (and this affects the whole intent of your "trick") comments are
removed before macros are expanded. The effect of this is that a macro
can't expand to a comment which seems to be what your trick is trying to
do.
In file included from src/verilog.cpp:16:
./include/verilog.h:35: error: expected unqualified-id before '/'
token

This is just the compiler ploughing on and not making sense of what the
erroneous macros have left behind.

gcc is quite correct to reject the code. What compilers accepted it?

Something like this:

#ifdef GLOBAL_VARS
#define EXT
#define INIT(...) = __VA_ARGS__
#else
#define EXT extern
#define INIT(...)
#endif

/* e.g. */
EXT int x INIT(42);
EXT int x[] INIT({1, 2, 3});

might suit but since the source would need to be re-written I'd probably
go for in GLOBAL macro:

#ifdef GLOBAL_VARS
#define GLOBAL(n, ...) n = __VA_ARGS__
#else
#define GLOBAL(n, ...) extern n
#endif

/* e.g. */
GLOBAL(int x, 42);
GLOBAL(int x[], {1,2,3});

The motivation seems to be based on having a large number of external
variables that you want to be able to define and to declare using just
one source. There may well be some other way to organise the code that
avoids the problem in the first place but it hard to know without seeing
the use to put these macros to.
 
L

Lola

As a general rule, I am wary of anything that can be called a
"preprocessor trick".  Often, the effect is to obfuscate the code so you
need to be sure that they pay their way, so to speak.




From the file name it looks like you may be using C++.  You should know
that there are differences between the two preprocessors and this may
matter.  In fact, the way I'd do what I think you are trying to do
relies on one of these differences.


The error message is accurate.  Presumably you know what ## does in a
macro body -- it joins two tokens into one -- and the message is
reporting that ;/ is not a valid token in C.  I'd guess the first ## is
simply not meant to be there.


This one, though accurate, is not so helpful.  Comments are treated as
white space so // is not, in fact, a valid preprocessing token.  What's
more (and this affects the whole intent of your "trick") comments are
removed before macros are expanded.  The effect of this is that a macro
can't expand to a comment which seems to be what your trick is trying to
do.


This is just the compiler ploughing on and not making sense of what the
erroneous macros have left behind.

gcc is quite correct to reject the code.  What compilers accepted it?

thanks for the prompt responce... It is a new program which I am about
to start and was just exorcising the best practice to use in it.. I'll
try the one below...

The compilers I have used with it so far are: VC++, armcc, and Zilog.
In embedded systems and the used of globals is done more often for
various reason.

Something like this:

  #ifdef GLOBAL_VARS
    #define EXT
    #define INIT(...)  = __VA_ARGS__
  #else
    #define EXT extern
    #define INIT(...)
  #endif

  /* e.g. */
  EXT int x INIT(42);
  EXT int x[] INIT({1, 2, 3});

might suit but since the source would need to be re-written I'd probably
go for in GLOBAL macro:

  #ifdef GLOBAL_VARS
    #define GLOBAL(n, ...) n = __VA_ARGS__
  #else
    #define GLOBAL(n, ...) extern n
  #endif

  /* e.g. */
  GLOBAL(int x, 42);
  GLOBAL(int x[], {1,2,3});

The motivation seems to be based on having a large number of external
variables that you want to be able to define and to declare using just
one source.  There may well be some other way to organise the code that
avoids the problem in the first place but it hard to know without seeing
the use to put these macros to.
 
S

Seebs

I am trying the folowing preprocessor trick with gcc but it doesn't
seem to work (worked with all the compilers I have used so far):

Blind luck.
#else
#define EXT extern
#define EQ ;##/##/

This is not valid. ## has to yield a single preprocessing token.

Some compilers will, by blind luck, ignore this -- because they're just
ramming the text together and hoping for the best.

-s
 
T

Thad Smith

Hi,

I am trying the folowing preprocessor trick with gcc but it doesn't
seem to work (worked with all the compilers I have used so far):

#ifdef GLOBAL_VARS
#define EXT
#define EQ =
#else
#define EXT extern
#define EQ ;##/##/
#endif

Here is a way that you can define and conditionally initialize a global variable
with C90 (Ben has shown a better way with C99):

#ifdef GLOBAL_VARS
#define GLOBAL
#else
#define GLOBAL extern
#endif

GLOBAL int foo[5]
#ifdef GLOBAL_VARS
= {1,2,3,4,5}
#endif
;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top