473,466 Members | 1,464 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

macros and side effects

Is it true that C macros are unsafe when combined with side effects even if
they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"? I have always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this problem...

I am wondering because I have just looked up putc() in a reference, and it
says that it is unsafe if the "passed" value has a side effect, and I assume
standard macros are "clean"...


May 4 '07 #1
20 3357
>>>>"c" == copx <co**@gazeta.plwrites:

cIs it true that C macros are unsafe when combined with side
ceffects even if they are "clean" e.g. could

cfoo_macro(++c);

#define foo_macro(x) (x)*(x)

Whoops.

Charlton

--
Charlton Wilbur
cw*****@chromatico.net
May 4 '07 #2
copx wrote:
Is it true that C macros are unsafe when combined with side effects even if
they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"? I have always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this problem...

I am wondering because I have just looked up putc() in a reference, and it
says that it is unsafe if the "passed" value has a side effect, and I assume
standard macros are "clean"...
Your reference is correct, and "clean" macros can evaluate their
arguments multiple times. As a simple example, if you have

#define foo_macro(x) ((x) * (x))

then foo_macro's arguments are fully parenthesised, but foo_macro(++c)
will still expand to ((++c) * (++c)).

For most standard library functions, it is required that if they are
also implemented as a macro, that that macro evaluates each argument
exactly once. putc is an exception.

May 4 '07 #3
copx said:
Is it true that C macros are unsafe
Not if written correctly and used correctly.
when combined with side effects even if they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"?
That is not a widely-used term for describing macros. (Translation: it's
the first time I have ever seen it.)
I have
always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this
problem...
You thought wrong.
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side effect,
Your reference says wrong. The putc function, if implemented as a macro,
may evaluate the stream more than once, but *not* the character. And
you're hardly likely to call it as putc('\n', fp++), I trust?
and I assume standard macros are "clean"...
Why?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 4 '07 #4
Richard Heathfield wrote:
copx said:
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side effect,

Your reference says wrong. The putc function, if implemented as a macro,
may evaluate the stream more than once, but *not* the character.
That's a useful clarification, but it doesn't mean the reference is
wrong.

May 4 '07 #5
Richard Heathfield wrote On 05/04/07 12:34,:
copx said:
>>[...] "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) [...]

and I assume standard macros are "clean"...


Why?
Perhaps because of the Standard? 6.10.8 lists the
values of the predefined macros, and all are "clean."
7.1.2p5 requires "cleanliness" of all object-like macros
defined in the standard headers, and 7.1.4p2 does the same
for function-like macros that implement standard library
functions. What remains are the dribs and drabs like
va_start() and setjmp(); do you find them "unclean" (in
the O.P.'s sense, that is)?

--
Er*********@sun.com
May 4 '07 #6
In article <gP******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>copx said:
>Is it true that C macros are unsafe

Not if written correctly and used correctly.
It's worth noting, though, that they're one of the easier parts of the
language to get wrong unintentionally, and it's sometimes easy to convert
correct use into incorrect use without realizing it, even if you do know
what you're doing.

If you compare programming in C to running with scissors, a lot of code
that uses macros ends up being at the pointy end of the scissors.
dave
(runs around the pool with scissors)

--
Dave Vandervies dj******@csclub.uwaterloo.ca
C is for people who run with scissors on a daily basis without cutting
themselves, because they know how to be careful around sharp tools.
--Richard Heathfield in comp.lang.c
May 4 '07 #7
copx wrote:
Is it true that C macros are unsafe when combined with side effects
even if they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"?
Yes.
I have
always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this
problem...
Because macros are essentially a form of text substitution, the
parentheses in a macro definition can not influence how often an
argument gets evaluated.

The parentheses around macro arguments are needed to ensure that the
parser always interprets the complete argument as a single expression.
For example, take these two macros:

#define HALVE(x) x/2
#define DIVIDE_BY_TWO(x) (x)/2

When you use them like this:

y = HALVE(3+1);
z = DIVIDE_BY_TWO(3+1);

the preprocessor will replace the macros, yielding:

y = 3+1/2;
z = (3+1)/2;

Do you see the difference between the two statements?
>
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side effect,
and I assume standard macros are "clean"...
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
May 4 '07 #8

"Bart van Ingen Schenau" <ba**@ingen.ddns.infoschrieb im Newsbeitrag
news:60****************@ingen.ddns.info...
copx wrote:
>Is it true that C macros are unsafe when combined with side effects
even if they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"?

Yes.
>I have
always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this
problem...

Because macros are essentially a form of text substitution, the
parentheses in a macro definition can not influence how often an
argument gets evaluated.

The parentheses around macro arguments are needed to ensure that the
parser always interprets the complete argument as a single expression.
For example, take these two macros:

#define HALVE(x) x/2
#define DIVIDE_BY_TWO(x) (x)/2

When you use them like this:

y = HALVE(3+1);
z = DIVIDE_BY_TWO(3+1);

the preprocessor will replace the macros, yielding:

y = 3+1/2;
z = (3+1)/2;

Do you see the difference between the two statements?
[snip]

Yes, I remember that much of kindergarten math ;)

Thanks everyone.


May 4 '07 #9

"Harald van D?k" <tr*****@gmail.comwrote in message
news:11**********************@c35g2000hsg.googlegr oups.com...
copx wrote:
>Is it true that C macros are unsafe when combined with side effects even
if
they are "clean" e.g. could

foo_macro(++c);

execute "++c" multiple times even if foo_macro is "clean"? I have always
thought that "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) do not have this problem...

I am wondering because I have just looked up putc() in a reference, and
it
says that it is unsafe if the "passed" value has a side effect, and I
assume
standard macros are "clean"...

Your reference is correct, and "clean" macros can evaluate their
arguments multiple times. As a simple example, if you have

#define foo_macro(x) ((x) * (x))

then foo_macro's arguments are fully parenthesised, but foo_macro(++c)
will still expand to ((++c) * (++c)).

For most standard library functions, it is required that if they are
also implemented as a macro, that that macro evaluates each argument
exactly once. putc is an exception.
Not "exactly once", but "at most once". It is quite legitimate for
some argument to not be evaluated at all.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Aero Stability and Controls Computing
May 4 '07 #10
Eric Sosman said:
Richard Heathfield wrote On 05/04/07 12:34,:
>copx said:
>>>[...] "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) [...]

and I assume standard macros are "clean"...


Why?

Perhaps because of the Standard? 6.10.8 lists the
values of the predefined macros, and all are "clean."
Those are macros such as __FILE__, and they don't take parameters, so I
don't see why they're relevant.
7.1.2p5 requires "cleanliness" of all object-like macros
defined in the standard headers,
Sure.
and 7.1.4p2 does the same
for function-like macros that implement standard library
functions.
7.1.4p2 (of C99 - there is no such paragraph in C89) says:

2 Provided that a library function can be declared without reference to
any type defined in a header, it is also permissible to declare the
function and use it without including its associated header.

I don't see how this says anything about parenthetical protection for a
function-like macro's arguments.
What remains are the dribs and drabs like
va_start() and setjmp(); do you find them "unclean" (in
the O.P.'s sense, that is)?
As far as I am aware, that depends on the implementation.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 4 '07 #11
Harald van D?k said:
Richard Heathfield wrote:
>copx said:
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side
effect,

Your reference says wrong. The putc function, if implemented as a
macro, may evaluate the stream more than once, but *not* the
character.

That's a useful clarification, but it doesn't mean the reference is
wrong.
It's wrong because of 4.1.6 (C89) and 7.1.4(1) (C99):

"Any invocation of a library function that is implemented as
a macro shall expand to code that evaluates each of its arguments
exactly once, fully protected by parentheses where necessary, so it is
generally safe to use arbitrary expressions as arguments."

....and that means that there is an apparent contradiction between the
above text and the description of putc in 4.9.7.8 (C89) and 7.19.7.8
(C99). Has this been the subject of any DRs?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 4 '07 #12
Dave Vandervies said:

<snip>
If you compare programming in C to running with scissors, a lot of
code that uses macros ends up being at the pointy end of the scissors.
Aye - it's snipped out, and discarded. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 4 '07 #13
Fred Kleinschmidt wrote On 05/04/07 14:20,:
"Harald van D?k" <tr*****@gmail.comwrote
>>
For most standard library functions, it is required that if they are
also implemented as a macro, that that macro evaluates each argument
exactly once. putc is an exception.

Not "exactly once", but "at most once". It is quite legitimate for
some argument to not be evaluated at all.
Not "at most once," but "exactly once," and it is
ILlegitimate to omit evaluating an argument. 7.1.4p1:

[...] Any invocation of a library function that is
implemented as a macro shall expand to code that
evaluates each of its arguments exactly once, fully
protected by parentheses where necessary, [...]

--
Er*********@sun.com

May 4 '07 #14
Richard Heathfield wrote On 05/04/07 14:55,:
Eric Sosman said:

>>Richard Heathfield wrote On 05/04/07 12:34,:
>>>copx said:
[...] "clean" macros (i.e. macros where all parameters are
surrounded by parentheses in the definition) [...]

and I assume standard macros are "clean"...
Why?

Perhaps because of the Standard?
[...]
and 7.1.4p2 does the same
for function-like macros that implement standard library
functions.


7.1.4p2 (of C99 - there is no such paragraph in C89) says:

2 Provided that a library function can be declared without reference to
any type defined in a header, it is also permissible to declare the
function and use it without including its associated header.

I don't see how this says anything about parenthetical protection for a
function-like macro's arguments.
My error: should have been p1, not p2.

"[...] Any invocation of a library function that
is ipmlemented as a macro shall expand to code
that evaluates each of its arguments exactly once,
fully protected by parentheses where necessary [...]"
>>What remains are the dribs and drabs like
va_start() and setjmp(); do you find them "unclean" (in
the O.P.'s sense, that is)?

As far as I am aware, that depends on the implementation.
Perhaps you're right. I shall henceforth avoid
code like

va_list array[10], *ap = array;
va_start (ap + 5, parmN);

.... even though it'll cramp my style.

--
Er*********@sun.com

May 4 '07 #15
Richard Heathfield <rj*@see.sig.invalidwrites:
Harald van D?k said:
>Richard Heathfield wrote:
>>copx said:
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side
effect,

Your reference says wrong. The putc function, if implemented as a
macro, may evaluate the stream more than once, but *not* the
character.

That's a useful clarification, but it doesn't mean the reference is
wrong.

It's wrong because of 4.1.6 (C89) and 7.1.4(1) (C99):

"Any invocation of a library function that is implemented as
a macro shall expand to code that evaluates each of its arguments
exactly once, fully protected by parentheses where necessary, so it is
generally safe to use arbitrary expressions as arguments."

...and that means that there is an apparent contradiction between the
above text and the description of putc in 4.9.7.8 (C89) and 7.19.7.8
(C99). Has this been the subject of any DRs?
There's no need for a DR. Go back to the beginning of paragraph C99
7.1.4p1:

Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow:
[...]

The description of putc() explicitly states otherwise.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
May 4 '07 #16
Richard Heathfield wrote:
>
.... snip ...
>
It's wrong because of 4.1.6 (C89) and 7.1.4(1) (C99):

"Any invocation of a library function that is implemented as
a macro shall expand to code that evaluates each of its arguments
exactly once, fully protected by parentheses where necessary, so
it is generally safe to use arbitrary expressions as arguments."

...and that means that there is an apparent contradiction between
the above text and the description of putc in 4.9.7.8 (C89) and
7.19.7.8 (C99). Has this been the subject of any DRs?
Note para. 2 below.

N869:
7.19.7.8 The putc function

Synopsis

[#1]
#include <stdio.h>
int putc(int c, FILE *stream);

Description

[#2] The putc function is equivalent to fputc, except that
if it is implemented as a macro, it may evaluate stream more
than once, so that argument should never be an expression
with side effects.

Returns

[#3] The putc function returns the character written. If a
write error occurs, the error indicator for the stream is
set and putc returns EOF.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

May 4 '07 #17
Richard Heathfield <rj*@see.sig.invalidwrote:
>
...and that means that there is an apparent contradiction between the
above text and the description of putc in 4.9.7.8 (C89) and 7.19.7.8
(C99). Has this been the subject of any DRs?
No, because the very first sentence of 4.1.6/7.1.4 resolves it:

Each of the following statements applies unless explicitly
stated otherwise in the detailed descriptions that follow:

So the explicit license in the description of putc takes precedence.

-Larry Jones

The hardest part for us avant-garde post-modern artists is
deciding whether or not to embrace commercialism. -- Calvin
May 4 '07 #18
Keith Thompson said:

<snip>
There's no need for a DR. Go back to the beginning of paragraph C99
7.1.4p1:

Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow:
[...]

The description of putc() explicitly states otherwise.
No fair! Expecting me to /read/ the thing, as opposed to merely
searching it...

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 5 '07 #19
CBFalconer said:
Richard Heathfield wrote:
>>
...and that means that there is an apparent contradiction between
the above text and the description of putc in 4.9.7.8 (C89) and
7.19.7.8 (C99). Has this been the subject of any DRs?

Note para. 2 below.
I was wrong, but that isn't why I was wrong.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
May 5 '07 #20
Richard Heathfield wrote:
>
Harald van D?k said:
Richard Heathfield wrote:
copx said:
I am wondering because I have just looked up putc() in a reference,
and it says that it is unsafe if the "passed" value has a side
effect,

Your reference says wrong. The putc function, if implemented as a
macro, may evaluate the stream more than once, but *not* the
character.
That's a useful clarification, but it doesn't mean the reference is
wrong.

It's wrong because of 4.1.6 (C89) and 7.1.4(1) (C99):

"Any invocation of a library function that is implemented as
a macro shall expand to code that evaluates each of its arguments
exactly once, fully protected by parentheses where necessary, so it is
generally safe to use arbitrary expressions as arguments."

...and that means that there is an apparent contradiction between the
above text and the description of putc in 4.9.7.8 (C89) and 7.19.7.8
(C99). Has this been the subject of any DRs?
There's two exceptions.
putc is one, getc is the other.

--
pete
May 5 '07 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: mike420 | last post by:
Tayss wrote: > > app = wxPySimpleApp() > frame = MainWindow(None, -1, "A window") > frame.Show(True) > app.MainLoop() > Why do you need a macro for that? Why don't you just write
8
by: Michael Winter | last post by:
In a recent post ("About C error" by Victor, 21 Sep 2003), comments were made about the poster's use of macros. What I would like to know is why they are considered bad? I'm not referring to...
3
by: Generic Usenet Account | last post by:
I have written a small macro that provides the relative offset of any field within a structure. Here it goes: #define RELATIVE_OFFSET(a,b) \ { \ cout << "The relative offset of the " \ <<...
5
by: Niklaus | last post by:
This is one of the posts that i got. ------------------------------ A "side effect" of an operation is something that *happens*, not something that *is produced*. Examples: In the expression...
2
by: Andrew Arro | last post by:
is it possible to make smth like a loop of macroses? i.e. i want some macros to be called X times, all that on the PREPROCESSOR lever i was trying smth like #define vv_0 100 #define vv_1...
33
by: Robert Seacord | last post by:
When writing C99 code is a reasonable recommendation to use inline functions instead of macros? What sort of things is it still reasonable to do using macros? For example, is it reasonable to...
27
by: Cephalobus_alienus | last post by:
Hello, I know that macros are evil, but I recently came across a problem that I couldn't figure out how to solve with templates. I wanted to create a set of singleton event objects, and wrote...
3
by: Floobar | last post by:
Macros sure can be fun -- and profitable. This actually worked -- it might work for any of you guys too. The trick is to make your code look sensible, but be actually very hard to modify without...
6
by: prashant.khade1623 | last post by:
HI All, I know the clear distinction between macro and function. I know that macro will speed up the program and using function will reduce the size. But how do we know when to use macro...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.