Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   preprocessor trick (http://www.velocityreviews.com/forums/t743351-preprocessor-trick.html)

Lola 02-10-2011 11:10 AM

preprocessor trick
 
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

Ben Bacarisse 02-10-2011 12:24 PM

Re: preprocessor trick
 
Lola <ivandiprima@gmail.com> writes:

> 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.

--
Ben.

Lola 02-10-2011 01:03 PM

Re: preprocessor trick
 
On Feb 10, 12:24*pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Lola <ivandipr...@gmail.com> writes:
> > 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?
>


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.
>
> --
> Ben.



Seebs 02-11-2011 08:05 PM

Re: preprocessor trick
 
On 2011-02-10, Lola <ivandiprima@gmail.com> wrote:
> 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
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Thad Smith 02-12-2011 06:02 PM

Re: preprocessor trick
 
On 2/10/2011 4:10 AM, Lola wrote:
> 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
;

--
Thad


All times are GMT. The time now is 10:00 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.