Conditional compilation inside a macro

S

Srinivas Mudireddy

Hi,
I am facing a problem with trying to conditionally compile inside a
macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to 0. So
I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro. Is
there any way I can get around this problem with still using a macro? I
can define a function to do the same, but I would prefer to use a
macro.

Thanks,
Srinivas
 
R

Rod Pemberton

Srinivas Mudireddy said:
Hi,
I am facing a problem with trying to conditionally compile inside a
macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to 0. So
I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro. Is
there any way I can get around this problem with still using a macro? I
can define a function to do the same, but I would prefer to use a
macro.

Does it fail with line continuation character, '\' backslash, at the end of
each line, except the last?

RP
 
C

CBFalconer

Srinivas said:
I am facing a problem with trying to conditionally compile inside
a macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to
0. So I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro.
Is there any way I can get around this problem with still using a
macro? I can define a function to do the same, but I would prefer
to use a macro.

#define SET_VAL(x, y) \
do { \
if (y) (x) = *(y); else (x) = 0; \
} while (0)

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
I

Ian Collins

Srinivas said:
Hi,
I am facing a problem with trying to conditionally compile inside a
macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to 0. So
I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro. Is
there any way I can get around this problem with still using a macro? I
can define a function to do the same, but I would prefer to use a
macro.
Why on Earth would you want to do that? Just use an inline function.
 
I

Ian Collins

CBFalconer said:
#define SET_VAL(x, y) \
do { \
if (y) (x) = *(y); else (x) = 0; \
} while (0)

Or
#define SET_VAL(x, y) ((x) = (y) ? *(y) : 0)

But still fragile, try invoking with NULL for y.
 
I

Ian Collins

Ian said:
Why on Earth would you want to do that? Just use an inline function.
Sorry, I thought I was down the hall in the C++ group where my
pathological hatred of macros belongs...
 
C

CBFalconer

Ian said:
Or
#define SET_VAL(x, y) ((x) = (y) ? *(y) : 0)

But still fragile, try invoking with NULL for y.

I see no difficulty with NULL.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
W

WaterWalk

Srinivas Mudireddy 写é“:
Hi,
I am facing a problem with trying to conditionally compile inside a
macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to 0. So
I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro. Is
there any way I can get around this problem with still using a macro? I
can define a function to do the same, but I would prefer to use a
macro.

Thanks,
Srinivas

Maybe this will work:
#define SET_VAL(x, y) ( y == NULL ? (x=0) : ((x) = *(y)))
 
P

pete

Ian said:
Or
#define SET_VAL(x, y) ((x) = (y) ? *(y) : 0)

But still fragile, try invoking with NULL for y.

It will work if y is a null pointer object,
which I think is probably sufficient,
because I don't think it makes sense to write
SET_VAL(x, NULL) in code,
when you know that zero is the value that you want there.
 
P

pete

CBFalconer said:
I see no difficulty with NULL.

((x) = (NULL) ? *(NULL) : 0)

The compiler won't translate the *(NULL) expression.
But as I implied elsethread, I think it's more likely
that OP was considering that y might be a null pointer lvalue,
than that OP would actually write
SET_VAL(x, NULL);
in his source code.
 
S

Serve Laurijssen

Ian Collins said:
Sorry, I thought I was down the hall in the C++ group where my
pathological hatred of macros belongs...

C knows inline functions too these days :)
 
J

Jordan Abel

Hi,
I am facing a problem with trying to conditionally compile inside a
macro. I have a macro

#define SET_VAL(x, y) ((x) = *(y))

But the problem is y can be NULL in which case I want to set x to 0. So
I modified macro to

#define SET_VAL(x, y)
#if y == NULL
x = 0;
#else
(x) = *(y);
#endif

This is not working since # has a special meaning inside a macro.

No, it's not working because preprocessor directives can only expand to
one line, and they cannot expand to other preprocessor directives.
Is
there any way I can get around this problem with still using a macro? I
can define a function to do the same, but I would prefer to use a
macro.

#define SET_VAL(x,y) ((x)=(y)?(*y):0)
 
S

Srinivas Mudireddy

WaterWalk said:
Srinivas Mudireddy 写é“:


Maybe this will work:
#define SET_VAL(x, y) ( y == NULL ? (x=0) : ((x) = *(y)))

Thx for the suggestion. I thought my simplified example will be enough,
but seems like it is confusing. There are 3 subsystems involved here.
Subsystem A talks about QoS in terms of structure X. Variables x and y
are of type X. Subsystem C tells subsystem B whether QoS is granted or
not in terms of structure M. B looks at M and checks if it has a
special value which means that QoS is not granted. If it is not, it
calls SET_VAL(x, NULL). If QoS is granted, it calls SET_VAL(x, y). When
NULL is passed, I would like to memset x with 0. So ternary operation
will not work.

I apologise for giving a wrong example and throwing you guys in wrong
direction.

Thx,
Srinivas
 
J

Jack Klein

Does it fail with line continuation character, '\' backslash, at the end of
each line, except the last?

If it does not "fail" with the modification you suggested, the
implementation is very severely non-conforming.
 
K

Keith Thompson

Srinivas Mudireddy said:
WaterWalk wrote: [...]
Maybe this will work:
#define SET_VAL(x, y) ( y == NULL ? (x=0) : ((x) = *(y)))

Thx for the suggestion. I thought my simplified example will be enough,
but seems like it is confusing. There are 3 subsystems involved here.
Subsystem A talks about QoS in terms of structure X. Variables x and y
are of type X. Subsystem C tells subsystem B whether QoS is granted or
not in terms of structure M. B looks at M and checks if it has a
special value which means that QoS is not granted. If it is not, it
calls SET_VAL(x, NULL). If QoS is granted, it calls SET_VAL(x, y). When
NULL is passed, I would like to memset x with 0. So ternary operation
will not work.

I apologise for giving a wrong example and throwing you guys in wrong
direction.

Why not just write it as a function? It's going to be a lot more
flexible and legible than a macro. It makes sense to use a macro
*only* if the operation is performance-critical *and* you're concerned
about compilers that don't support inline functions.
 
R

Rod Pemberton

Jack Klein said:
If it does not "fail" with the modification you suggested, the
implementation is very severely non-conforming.

True #if-#else-#endif. The point was to get him thinking about a solution
which CBFalconer posted outright...

RP
 
C

CBFalconer

obdict said:
Do you have to guard against the scenario that y might be void*?

I dunno. It would seem to depend on the usage of y. Without any
context that is totally unknown.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
C

Chris Torek

[regarding defining a macro weirdly]

Thx for the suggestion. I thought my simplified example will be enough,
but seems like it is confusing. ...
[In one case, other code the OP probably did not write]
calls SET_VAL(x, NULL).
[In a completely different case, that other code]
calls SET_VAL(x, y). When NULL is passed, I would like to memset x
with 0. So ternary operation will not work.

It can still be made to work using a variant like the one someone
suggested, e.g.:

#define SET_VAL(x, y) \
((y) == NULL ? \
(void)memset(&(x), 0, sizeof(x)) : \
(void)((x) = *(y)))

However, this strikes me as solving the wrong problem, which can
be re-described as follows:

"Some code I did not write insists on using macro X with
particular arguments for situation A, and the same macro X with
different arguments for completely different situation B."

The question was then:

"How can I write a complicated version of macro X that
distinguishes between the two situations based on one of the
arguments?"

when the obvious "right" approach is: "Change the other code to
use two *different* macros for the two different situations."
(Given the text I snipped, possible macros might be something like
"ALLOW_QoS" and "DENY_QoS". The "DENY" macro would take only one
argument, rather than two.)

That is, fix the real problem, rather than kludging up a work-around.

(Of course, sometimes fixing the real problem is rejected; occasionally
it is even rejected for a good reason.)
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top