Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Changing from && to ||

3 views
Skip to first unread message

James Harris

unread,
Mar 24, 2010, 7:31:29 AM3/24/10
to
In a macro I have a function of the form

(a) >= (b) && f(a, b)

and I think it may be incorrect. The idea is that the function is
called only if a >= b but the expression should also return true if a
< b. I guess what I have will return false so I'm thinking to change
it to

(a) < (b) || f(a, b)

So, if a < b it will return true and not call the function. If a >= b
it will call the function and return the result of the function call.

Have I got the change right?

James

Nick Keighley

unread,
Mar 24, 2010, 7:46:00 AM3/24/10
to
On 24 Mar, 11:31, James Harris <james.harri...@googlemail.com> wrote:

> In a macro I have a function of the form
>
>   (a) >= (b) && f(a, b)

something like
#define C_CALL(a,b) (a) >= (b) && f(a, b)

I'd want an extra set of brackets
#define C_CALL(a,b) ((a) >= (b) && f(a, b))

Are you sure you'll never call it like this?
C_CALL (x++, y);


> and I think it may be incorrect. The idea is that the function is
> called only if a >= b but the expression should also return true if a
> < b.

will this do what you want?

#define C_CALL(a,b) ((a) >= (b) && (f(a, b) , 1))

> I guess what I have will return false so I'm thinking to change
> it to
>
>   (a) < (b) || f(a, b)
>
> So, if a < b it will return true and not call the function. If a >= b
> it will call the function and return the result of the function call.
>
> Have I got the change right?

I think so, but it all looks unnecessarily devious

James Harris

unread,
Mar 24, 2010, 8:15:51 AM3/24/10
to
On 24 Mar, 11:46, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

> On 24 Mar, 11:31, James Harris <james.harri...@googlemail.com> wrote:
>
> > In a macro I have a function of the form
>
> >   (a) >= (b) && f(a, b)
>
> something like
> #define C_CALL(a,b) (a) >= (b) && f(a, b)
>
> I'd want an extra set of brackets
> #define C_CALL(a,b) ((a) >= (b) && f(a, b))
>
> Are you sure you'll never call it like this?
>     C_CALL (x++, y);
>
> > and I think it may be incorrect. The idea is that the function is
> > called only if a >= b but the expression should also return true if a
> > < b.
>
> will this do what you want?
>
> #define C_CALL(a,b) ((a) >= (b) && (f(a, b) , 1))

I think that will return 1 if the function is called. It should
instead return the result of the function call (which is 1 or 0).

> > I guess what I have will return false so I'm thinking to change
> > it to
>
> >   (a) < (b) || f(a, b)
>
> > So, if a < b it will return true and not call the function. If a >= b
> > it will call the function and return the result of the function call.

In full it would be, using your format,

#define C_CALL(a, b) ((a) < (b) || f((a), (b)))

> > Have I got the change right?
>
> I think so, but it all looks unnecessarily devious

Is it more devious than other macros? It doesn't use ?: so is easier
to read than many. When called it would be something like

if (C_CALL(a, b)) { ... }

James

Dr Malcolm McLean

unread,
Mar 24, 2010, 9:58:29 AM3/24/10
to
I'd write it as

(( (a) >= (b) ) ? f( (a), (b) ) : true)

It's not obvious from your macro that the return is important.

Thad Smith

unread,
Mar 24, 2010, 12:27:16 PM3/24/10
to

It will be obvious when the OP uses a suitable macro name, such as
BUFFER_IS_FULL, and when the macro is commented as returning a boolean value.

--
Thad

Nick Keighley

unread,
Mar 24, 2010, 11:55:23 AM3/24/10
to

no, its just putting stuff like this in macros is generally devious


It doesn't use ?: so is easier
> to read than many. When called it would be something like
>
>   if (C_CALL(a, b)) { ... }
>

> James- Hide quoted text -
>
> - Show quoted text -

James Harris

unread,
Mar 25, 2010, 7:18:48 AM3/25/10
to
On 24 Mar, 13:58, Dr Malcolm McLean <malcolm.mcle...@btinternet.com>
wrote:
...

> > In full it would be, using your format,
>
> > #define C_CALL(a, b) ((a) < (b) || f((a), (b)))
>
> > > > Have I got the change right?
>
> > > I think so, but it all looks unnecessarily devious
>
> > Is it more devious than other macros? It doesn't use ?: so is easier
> > to read than many.
>
> I'd write it as
>
> (( (a) >= (b) ) ? f( (a), (b) ) : true)
>
> It's not obvious from your macro that the return is important.

I see your point. Given just the info in my query it's not obvious
whether a return value is expected or not. But I can't quite take to
the ?: form if it's not needed.

Maybe we should expect (not mentally elide) a return value.

Speaking for myself

(c) && f()

looks much more familiar than

(c) || f()

and flows better mentally. I guess I tend to read the first as: if c
then *do* f(). The second, using ||, being less familiar is harder to
read. It could be: if not c then do f(). However, it also returns true
if c is true so including "not c" when reading it is misleading.

Perhaps it's better read as: if c then do nothing, otherwise do f().

And then if used in a boolean context: if c return 1, otherwise return
f().

So, using "return" in the non-keyword sense, maybe it's better to read
both conditional expressions as

(c) && f() becomes if c return f(), else return 0
(c) || f() becomes if c return 1, else return f()

I hope that's right. No doubt someone will correct me if not.

James

pete

unread,
Mar 25, 2010, 8:05:23 AM3/25/10
to

It isn't right.

The value of ((c) && f()) is either one or zero.
The value of ((c) || f()) is either one or zero.


--
pete

James Harris

unread,
Mar 25, 2010, 8:12:51 AM3/25/10
to
On 24 Mar, 15:55, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
...

> > Is it more devious than other macros?
>
> no, its just putting stuff like this in macros is generally devious
>
>  It doesn't use ?: so is easier

I do agree. Putting stuff like this in macros is not generally a good
idea. I'll explain why I did in this case. See if it makes it any more
palatable.

It's from my xbuf routines

http://codewiki.wikispaces.com/xbuf.c

They include a called routine which, if necessary, increases the size
of a buffer. It carries out the following test

if (buffer is not big enough) {expand the buffer}

If used naively the buffer would be big enough most of the time and so
the called routine would return having done nothing except wasted
time. I wanted to make the routine suitable for use in tight loops.
How? The idea is that the calling code carries out the *same test*
before calling the routine so we get in the user's code

if (buffer is not big enough) {call the routine}

Depending on architecture and compiler this should compile to
something like two instructions: a simple test and a branch. With
modern branch prediction the cost of these two instructions would
virtually disappear and would be much faster than only carrying out
the test in a subroutine call.

I could expect the user of the routine to include the code for the
test but that commits some sins, in increasing order of sinfulness...

1) bulks up the caller's code,
2) diverts attention away from the normal flow and the user's
application logic and,
3) exposes some of the internals of the called routine to the
programmer using the routine.

Using a macro avoids these issues. Of course, being in all capitals
the macro name serves as the usual warning about parameter evaluation.

So, I think the macro is pragmatic and the right thing to do in this
case. YMMV. The better solution, IMHO, would be if we could depend on
optimisation between procedures - but that's another topic.

James

Ben Bacarisse

unread,
Mar 25, 2010, 8:16:06 AM3/25/10
to
James Harris <james.h...@googlemail.com> writes:
<snip>

> So, using "return" in the non-keyword sense, maybe it's better to read
> both conditional expressions as
>
> (c) && f() becomes if c return f(), else return 0
> (c) || f() becomes if c return 1, else return f()
>
> I hope that's right. No doubt someone will correct me if not.

In your specific case, yes, but only because f() returns 0 or 1. I'd
choose between c && f() and c ? f() : 0 depending on what I wanted the
reader to focus on -- the Boolean nature of the expression or the
return value of f().

--
Ben.

Thad Smith

unread,
Mar 25, 2010, 4:22:30 PM3/25/10
to
James Harris wrote:
> On 24 Mar, 15:55, Nick Keighley <nick_keighley_nos...@hotmail.com>
> wrote:
[Regarding Jim Harris's comment]

>>>In full it would be, using your format,
>>>
>>> #define C_CALL(a, b) ((a) < (b) || f((a), (b)))
>>>
>>> Is it more devious than other macros?
>> no, its just putting stuff like this in macros is generally devious
>>
>> It doesn't use ?: so is easier
>
> I do agree. Putting stuff like this in macros is not generally a good
> idea. I'll explain why I did in this case. See if it makes it any more
> palatable.

[good rationale for using a similar macro given]

> I could expect the user of the routine to include the code for the
> test but that commits some sins, in increasing order of sinfulness...
>
> 1) bulks up the caller's code,
> 2) diverts attention away from the normal flow and the user's
> application logic and,
> 3) exposes some of the internals of the called routine to the
> programmer using the routine.
>
> Using a macro avoids these issues. Of course, being in all capitals
> the macro name serves as the usual warning about parameter evaluation.
>
> So, I think the macro is pragmatic and the right thing to do in this
> case. YMMV.


I agree with your conclusion that it makes sense in such circumstances,
especially with corresponding naming and documentation of the macro. I disagree
with your earlier comment that "Putting stuff like this in macros is not
generally a good idea". I think of such a macro as basically a short function.
You describe what it does. You can easily verify it. No problem.

--
Thad

Peter Nilsson

unread,
Mar 25, 2010, 8:11:00 PM3/25/10
to

Use the turnary ?: operator to make it explicit...

#define BLAH(a,b) \
( (a) < (b) ? 1 : (f(a, b) != 0) )

--
Peter

0 new messages