>I was wondering why it seems that the comma operator is so rarely used.
>The only time I ever see it is in 'for' loops. Is it really considered
>*that* bad by the programming public at large? Any comments?
I don't think it's _bad_; it's just not very useful except in for
loops. At least, I can't think of why I'd use it elsewhere.
--
spco...@uokmax.ecn.uoknor.edu
Support your local medical examiner - die strangely
It is kind of hard to see commas in the morass of other punctuation that
C always involves. I occasionally use it if I'm incrementing two pointers
at the same time, and there's nothing else in the loop body, rather than
tying up all sorts of extra space with brackets. (I'm NOT a K&R style lover)
Like everything else, I suppose, it's good if used right and bad if used
wrong.
De
--
== morons have no questions. ==
Mark: I was wondering why it seems that the comma operator is so rarely used.
Mark: The only time I ever see it is in 'for' loops. Is it really considered
Mark: *that* bad by the programming public at large? Any comments?
Steve: I don't think it's _bad_; it's just not very useful except in for
Steve: loops. At least, I can't think of why I'd use it elsewhere.
Rob: Well, I hadn't seen it used much either outside of the for loop, but
Rob: in Plaugher's latest book I discovered quite a few of the following
Rob: constructs:
Rob: if (condition)
Rob: var = value, anothervar = anothervalue;
Rob: This does away with the need for braces. I am tempted to use this myself
Rob: unless someone has a good point agains using this style. Opinions anyone?
That is the type of thing I was thinking of, along with:
for (expr1; expr2; expr3)expr4, expr5;
It shouldn't make any difference to a compiler whether you use braces or
just seperate them with a comma, so I was wondering why I never seem to
see code that has something like this. Obviously, this could be abused
and you could have an entire program full of:
for (expr1, expr2, expr3; expr4, expr5, expr6; expr7, expr8,
expr9) expr10, expr11, expr12, expr13, etc.
But for simple things that involve 2 or even 3 expressions, it seems
like it isn't that bad to do something like this. I mean, I have seen:
if (a<b)
{ temp = a; a = b; b = temp; }
why not:
if (a<b) temp = a, a = b, b = temp;
Some people seem to like braces ALWAYS on if/for/while's, even if there
is only one expression. I guess it is just a matter of personal
preference, but I think the second example directly above reads
well, and the intentions are clear. Like everything, of course, there
is room for abuse.
>> I don't think it's _bad_; it's just not very useful except in for
>>loops. At least, I can't think of why I'd use it elsewhere.
I find it useful in while loops, as in:
unsigned i;
FILE *f;
....
while (i = getw(f), !feof(f))
{
....
-------------------------------------------------------------------------
Graham Kean gk...@ccu1.aukuni.ac.nz
University of Auckland
-------------------------------------------------------------------------
I think it's mostly a matter of style. Many people learn their style from
the books or other programmers they learned from, so there tends to be some
amount of consistency across the industry. I've never seen commas used
extensively in the above ways in text books or code I've seen, so it tends
not to perpetuate.
As for why the style setters don't use that style, I can think of several
possible reasons.
First, many C programmers were formerly programmers in other languages, and
most other languages don't have anything like the comma operator. They
learned to use it in those special cases where it really solves a problem,
such as the for-statement, but in other cases they stick to their old
statement-oriented habits.
Second, there's a level of consistency and simplicity maintained when you
use statement sequencing rather than expression sequencing. It's easier to
use the same style for all compound statement bodies. If you sometimes use
comma, then you have to remember to switch to semicolon when the body
includes non-expression statements. However, semicolon works all the time.
A similar argument applies to why some people put braces around the body
even when there's only one statement. It allows you to code a bit more by
reflex, rather than having to think about minute details. Also, it allows
you to add more statements to the body with the minimal amount of editing;
it's already set up for a sequence of statements, so you can just add and
delete statements as needed, without having to add extraneous syntax.
--
Barry Margolin, Thinking Machines Corp.
bar...@think.com
{uunet,harvard}!think!barmar
Yeah... I have found it useful in the following context:
(video_mode() == 7) ? (background = BLACK, foregound = WHITE) :
(background = CYAN, foreground = MAGENTA);
when accounting for colour vs mono cards under MS-DOS. (I don't really
use magenta on cyan <g>). Just think of the number of lines that
I've saved compared to if I'd used if..else and braces (and I don't
think it's hard to read).
Just my $0.02...
cheers,
John Nash | Internet: Na...@biologysx.lan.nrc.ca
Institute for Biological Sciences | or: num2...@mbds.nrc.ca
National Research Council of Canada| Ottawa, Canada K1A 0R6.
==> Disclaimer: All opinions are mine, not NRC's! <==
>la...@lobster.cps.msu.edu (Mark M Lacey) writes:
>>I was wondering why it seems that the comma operator is so rarely used.
>>The only time I ever see it is in 'for' loops. Is it really considered
>>*that* bad by the programming public at large? Any comments?
> I don't think it's _bad_; it's just not very useful except in for
>loops. At least, I can't think of why I'd use it elsewhere.
Well, I hadn't seen it used much either outside of the for loop, but
in Plaugher's latest book I discovered quite a few of the following
constructs:
if (condition)
var = value, anothervar = anothervalue;
This does away with the need for braces. I am tempted to use this myself
unless someone has a good point agains using this style. Opinions anyone?
Rob Tulloh
--
INTERACTIVE Systems Corp. Tel: (512) 343 0376 Ext. 116
9442 Capital of Texas Hwy. North Fax: (512) 343 0376 Ext. 161 (not a typo!)
Arboretum Plaza One, Suite 700 Net: rob...@isc.com (polled daily)
Austin, Texas 78759 GEnie: R.TULLOH (polled monthly)
Actually, I sometimes find it useful in macros. If I need to perform
multiple statements, yet still have my macro "return" a value, the comma
operator is useful.
#define mymac(a) (foo(a), bar(a))
Calls both foo() and bar(), but the "return code" of mymac is the value
returned by bar().
--
------------------------------------------------------------------
stratsft!dwayne + Strategic Software IS me, so my
Dwayne Bailey + opintions ARE those of my
Strategic Software + company
Besides which, in any reasonable editor (with macro support), generating
the braces and placing them correctly is a single key-stroke.
--
_
Kevin D. Quitt srhqla!venus!kdq kdq%ve...@sr.com
3D systems, inc. 26081 Avenue Hall Valencia, CA 91355
VOICE (805) 295-5600 x430 FAX (805) 257-1200
96.37% of all statistics are made up.
The biggest reason I have for avoiding this type of construct is that some
source-level debuggers will single step over the entire statement in one step.
You can't step into the expression if you want to analyze it subexpression by
subexpression.
In fact, I even avoid:
> if (a<b)
> { temp = a; a = b; b = temp; }
because, similarly, the debugger may step over the entire line rather than step
statement by statement.
To see exactly what I mean, compile the following code:
main()
{
int a, b;
a=1; b=2;
a=1;
b=2;
a=1, b=2;
a=1,
b=2;
}
and try stepping through it with a debugger (I used dbxtool on a Sun/SunOS 4.1.1).
Of course, if you write bug-free code this argument doesn't apply. :-)
--
Todd Pfaff \ Internet: to...@flex.eng.mcmaster.ca
Dept. of Mechanical Engineering \ Voice: (416) 525-9140 x2902
McMaster University \ FAX: (416) 572-7944
Hamilton, Ontario, CANADA L8S 4L7 \
Nope, it will be interpreted as x(1, 2, 3). Look at the grammar in K&R2 page
237 and 238. Only assignment-expressions are allowed as actual parameters to
a function. And assignment-expressions don't have the comma operator in them.
regards,
Jos
|_Jos_Horsmeie...@and.nl_| J.F. Kennedy `Ich bin ein Berliner' |
| O O \O/ O O \O | R. Nixon `I am not a crook' |
|<|> <|/ | <|> \|> |> everybody | R. Reagan `I uhhh ...' |
|/ \ / / \ / \ \ / \ twist! | G. Bush `I don't like broccoli' |
| Zappa for president of the USA | F. Zappa `I am a Hamburger' |
>The way I remember it expr,expr is allowed wherever a single expr is.
>Right? Ok, let's say we have this:
>int x(int,int);
>....
>x(1,2,3);
>how would this be interpreted? x(1,(2,3)) or x((1,2),3) ???
I'm assuming a smiley was omitted on this posting, but I have seen
other postings imply that the comma separating function parameters
is the comma operator.
It isn't.
The comma in a function call is part of the call syntax, not part of
any expression serving as an actual parameter. C syntax does not allow
a comma as the top level operator in an actual parameter. If you want
a comma-expression as a parameter, you need to enclose the expression
in parentheses.
Assuming a suitable declaration for x(), the four function calls
x(1, 2, 3) /* 3 parameters */
x(1, (2,3)) /* 2 parameters */
x((1,2), 3) /* 2 parameters */
x((1,2,3)) /* 1 parameter */
are all different, and none is ambiguous.
--
Steve Clamage, TauMetric Corp, st...@taumet.com
>loops. At least, I can't think of why I'd use it elsewhere.
The way I remember it expr,expr is allowed wherever a single expr is.
> The way I remember it expr,expr is allowed wherever a single expr is.
> Right? Ok, let's say we have this:
> int x(int,int);
> x(1,2,3);
> how would this be interpreted? x(1,(2,3)) or x((1,2),3) ???
You've just answered your own question: expr,expr is not allowed
everywhere a single expr is. In particular, the expressions in
argument lists may not have commas unless those commas appear
in parenthesized subexpressions. Thus x(1,2,3) calls x with
three arguments, and you can write x(1,(2,3)) or x((1,2),3)
if that's what you mean.
--
--Andrew Koenig
a...@europa.att.com
But the arguments to functions are not expressions, thery are assignment-
expressions, which to not allow the comma operator. From the C grammar in
Appendix A of K&R2 (I would quote the ANSI standard, but I am poor
student who can't afford to buy it):
expression:
assignment-expression
expression , assignment-expression
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
postfix-expression:
[...]
postfix-expression ( argument-expression-list[opt] )
[...]
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression
[P.S. postfix-expr : postfix-exp ( argument-exp-list[opt] )
is the production corresponding to a function call.]
--
David Olsen
d...@cs.wisc.edu
So, has anyone discovered any good reason to overload the comma operator?
===========================================================================
Josh Mittleman (mit...@watson.ibm.com or jos...@paul.rutgers.edu)
J2-C28 T.J. Watson Research Center, PO Box 704, Yorktown Heights, NY 10598
Oldtime C++ hackers tend to run away screaming whenever they see a comma.
[....after debugging thousands of lines of Cfront output, containing tens
of thousands of commas.... :-]
Huh? Its "meaning" is to insert a sequence point between
the preceding and following expressions, returning the
value of its right-hand operand.
In this case (a little crocked) only the sequence-point
feature is used (twice!):
int i;
unsigned j;
for ( i = 0, j = i + 1; i <= MAX_FACTOR; i++, j *= i )
printf( "i! = %u\n", j );
placing the initializer for `j' outside the `for' would
be obfuscatory. It's debatable whether the `j *= i'
should be in the `printf' or the `for' or between them.
In this case (again a little crocked), only the
last-value feature is used:
int i, j;
extern int a[], b[]; /* int a[MAX], b[MAX]; */
i = -1;
j = MAX;
while ( i++, j-- )
a[i] = b[j]; /* reverse arrays */
Doing `a[++i] = b[--j]' would be a clear obfuscation.
Both versions can be cleaned up and made really nasty with
trebly-linked-lists and b-tree next-pointers instead of
integer indexes to arrays, such that it would make
incontrovertible sense to use the comma-operator in the
loop expressions.
--Blair
"Makeup exams will be given tomorrow.
Bring a No. 2 Eyebrow pencil and
your programming berets..."
-If Cindy Crawford taught C
I was wondering why it seems that the comma operator is so rarely used.
The only time I ever see it is in 'for' loops. Is it really considered
*that* bad by the programming public at large? Any comments?
Well, two things come to mind:
a) People forget that it's an operator, or what it means.
b) Good compilers will treat ';' the same way as ',' anyway, modulo
variable references.
Amanda Walker ama...@visix.com
Visix Software Inc. ...!uunet!visix!amanda
--
"I think there's a world market for about 5 computers."
--Thomas J. Watson, Chairman of the Board, IBM (around 1948)
>In article <1991Sep19....@uokmax.ecn.uoknor.edu> spco...@uokmax.ecn.uoknor.edu (Steve Coltrin) writes:
>>la...@lobster.cps.msu.edu (Mark M Lacey) writes:
>>
>>>I was wondering why it seems that the comma operator is so rarely used.
>>>The only time I ever see it is in 'for' loops. Is it really considered
>>>*that* bad by the programming public at large? Any comments?
>>
>> I don't think it's _bad_; it's just not very useful except in for
>>loops. At least, I can't think of why I'd use it elsewhere.
>>
>Actually, I sometimes find it useful in macros. If I need to perform
>multiple statements, yet still have my macro "return" a value, the comma
>operator is useful.
>#define mymac(a) (foo(a), bar(a))
>Calls both foo() and bar(), but the "return code" of mymac is the value
>returned by bar().
Yes, I have done this quite a bit too. I think outside of for loops, this
is the most used construct involving comma. I had not seen the if,else
use until I read Plauger's book.
IMHO, one could definitely overuse comma, but in some cases I think
it makes the code more readable. How about those X11 function calls
which need to bump through an array of arguments to be passed dynamically.
I am not an X programmer, but it seems like this might be another place where
using the comma might improve readability...
XtSetArg(args[i], XtNwidth, value), i++;
I believe the examples I have seen use semicolon instead of comma. This
might be even more useful if these 2 statements needed to be lumped
under an if/else statement.
Just my $0.02 worth!
spco...@uokmax.ecn.uoknor.edu (Steve Coltrin) writes:
>la...@lobster.cps.msu.edu (Mark M Lacey) writes:
Mark>I was wondering why it seems that the comma operator is so rarely used.
Mark>The only time I ever see it is in 'for' loops. Is it really considered
Mark>*that* bad by the programming public at large? Any comments?
Steve> I don't think it's _bad_; it's just not very useful except in for
Steve>loops. At least, I can't think of why I'd use it elsewhere.
Rob>Well, I hadn't seen it used much either outside of the for loop, but
Rob>in Plaugher's latest book I discovered quite a few of the following
Rob>constructs:
Rob> if (condition)
Rob> var = value, anothervar = anothervalue;
Rob>This does away with the need for braces. I am tempted to use this myself
Rob>unless someone has a good point agains using this style. Opinions anyone?
Consider this:
if (condition)
var = value; anothervar = anothervalue;
Only one little dot is changed, but the meaning is quite different. In other
words, using the comma operator like that makes it harder to read: It's
harder to get an overview of the code, because you have to be wary of that
subtle difference. And if you trust your indentation, you risk doing
something like the the famous FORTRAN error that caused a spacecraft bound
for Jupiter to fly astray (a `.' that should have been a `,').
In other places I find the comma operator extremely useful.
Primarily in macro definitions, where I want to do several things in a
single expression. And sometimes in the `init' and `next' parts of a
for(init;endcondition;next) body
loop, if the loop traverses two things simultaneously.
But I recommend against using the comma operator for the `if' or
loop body, for the above reasons.
BTW, the comma operator really is a lovely surprise for the Pascal
programmer, new to C, trying to index a twodimensional array like this:
char theArray[Range1][Range2];
...
printf("%c", theArray[index1,index2]);
...
- Anders Munch
ju...@diku.dk
>Mark: I was wondering why it seems that the comma operator is so rarely used.
>Rob: Well, I hadn't seen it used much either outside of the for loop, but
>Rob: in Plaugher's latest book I discovered quite a few of the following
>Rob: constructs:
>
>Rob: if (condition)
>Rob: var = value, anothervar = anothervalue;
>
>That is the type of thing I was thinking of, along with:
>
> for (expr1; expr2; expr3)expr4, expr5;
> if (a<b) temp = a, a = b, b = temp;
I use it all the time (especially in IOCCC entries :-) ), either as in the
above (except without the spaces :-)), or in a more complex thing, like
while(i++<j)
x=some_action(i),
y=other_result(i),
do_something(x,y),
etc, etc;
the_next_bit();
It somehow looks better without braces. The way it is written clearly
indicates the structure, and IMHO it doesn't matter whether the punctuation
marks are commas or semicolons, or whether or not there are braces. It does
make it easier to make mistakes, though usually the compiler detects it. The
most common is introducing an if or for statement, which cannot be preceded
by a comma.
Doing this has one noticeable effect that hasn't yet been mentioned. I use
the Sunview version of the symbolic debuger dbx (while it isn't perfect it
often does the job), and in single step mode all the above expressions
separated by commas are executed at once. This means I can change the code
around so that the parts that work are always executed quickly, and the
parts that don't are single stepped properly.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
But really, who (besides a COBOL programmer) would write code with that
deliberately misleading structure?
if(condition)
conditional-statement; unconditional-statement;
I think you're taking your argument beyond the realm of reality, here.
Regards,
John Kapson
Right.
Always code as if the guy who ends up maintaining your code will be a
violent psychopath who knows where you live. Code for readability.
>spco...@uokmax.ecn.uoknor.edu (Steve Coltrin) writes:
>>la...@lobster.cps.msu.edu (Mark M Lacey) writes:
>>>I was wondering why it seems that the comma operator is so rarely used.
>>>The only time I ever see it is in 'for' loops. Is it really considered
>>>*that* bad by the programming public at large? Any comments?
>> I don't think it's _bad_; it's just not very useful except in for
>>loops. At least, I can't think of why I'd use it elsewhere.
>Well, I hadn't seen it used much either outside of the for loop, but
>in Plaugher's latest book I discovered quite a few of the following
>constructs:
> if (condition)
> var = value, anothervar = anothervalue;
>This does away with the need for braces. I am tempted to use this myself
>unless someone has a good point agains using this style. Opinions anyone?
Before you make a decision like this, you might want to gaze at some
CFRONT output for awhile. This will almost certainly make you HATE
the comma operator.
--
+---Robert C. Martin---+-RRR---CCC-M-----M-| R.C.M. Consulting |
| rma...@rational.com |-R--R-C----M-M-M-M-| C++/C/Unix Engineering |
| (Uncle Bob.) |-RRR--C----M--M--M-| OOA/OOD/OOP Training |
+----------------------+-R--R--CCC-M-----M-| Product Design & Devel. |
The reason you see it so seldom is because it is most often used in
macros, which you aren't supposed to see.
#define poolcash(d,c) ( (d)+=(int)(c)/100 , (c)%=100 , (d)*100+(c) )
This type of macro is speedy because it skips the function overhead.
It works on registers, which a function can't do. It also returns a
value which a "do { ... } while(0)" type macro does not.
Fenn @wpi.wpi.edu
>int x(int,int);
>....
>x(1,2,3);
Congratulations! You have discovered one of the ugliest warts on the
otherwise beautiful C language. Comma has different semantics in
a function call argument list than elsewhere. This is similar to the
way * and & are overloaded as unary and binary operators with totally
unrelated meanings. So,
x(1,2,3); /* Passes 1, 2, and 3 to x */
x((1, 2), 3); /* Passes 2 and 3 to x */
Ugly, yet true. Still, this is probably more of a headache for compiler
writers than for C users.
- Craig Berry
"The man with no .sig file"
I've always believed that it should be CARVED IN STONE that one should
always, always, always, without exception, code macros so that arguments
are evaluated EXACTLY ONCE and ONLY ONCE. Not less than once and not
more than once.
#define mymac(a) (foo(a), bar(a))
main() {
int a = 1;
printf("a started out as %d in main\n", a);
printf("mymac(a++) returned %d\n", mymac(a++));
printf("a ended up as %d in main\n", a);
printf("This is easily explainable, but may be suprising.\n");
printf("Especially if the #definition of mymac(a)\n");
printf("is hidden in a header file.\n");
}
foo(a)
{
return(1234);
}
bar(a)
{
return(5678);
}
--
mitc...@mdi.com (Bill Mitchell)
Damn right!
--
mitc...@mdi.com (Bill Mitchell)
I belive that you have an error in here. The variables 'b' and 'e' are not
set to a value before they are used.
int a=1E4,b=0,c=2800,d,e=0,f[2801],g;main(){for(;b-c;f[b++]=a/5);for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}
Sorry, I don't agree with you. When you look at the grammar rules, page 237
of K&R2 (at least in my copy), you'll find an expression defined as one
or more assignment-exprs, separated by the comma operator. Page 238 shows
an argument expression list defined as one or more assignment-exprs, so
this comma stuff *is* clearly defined. It is not much of a headache for
compiler writers.
What I *do* find ugly is something like this:
typedef int T; /* T is a new type */
int T; /* Beng! redefinition */
struct T { /* T is fine as a struct tag ... */
T T; /* All's fine in here! */
...
} T; /* Beng! redef again! */
Have you ever tried to write a proper lexical analyser for this kludge?
This gave *me* a headache ... name spaces, pfah!
Jos aka j...@and.nl
extern errorcode sysfunction(int *returnvalue,args...);
...
int junk;
if (sysfunction(&junk,1,2,3),junk) {...
Bill Spitzak, a disillusioned hacker.
spco...@uokmax.ecn.uoknor.edu (Steve Coltrin) writes:
>la...@lobster.cps.msu.edu (Mark M Lacey) writes:
Mark>I was wondering why it seems that the comma operator is so rarely used.
Mark>The only time I ever see it is in 'for' loops. Is it really considered
Mark>*that* bad by the programming public at large? Any comments?
I've used it to make large macros act like functions which return a value
like this:
#define stuff(x,y) exp1, exp2, exp3
where exp{1,2,3} are expressions.
The key point is that the value of stuff(x,y) is the value of exp3. It's
analogous to a function doing
return exp3;
It may be smart to parenthesize the right hand side of the macro.
--
| UUCP-stuff: rutgers!devon!sojurn!mike | "It muddles me rather" |
| Slow-stuff: 2129 Old Phila. Pike | Winnie the Pooh |
| Lancaster, Pa. 17602 | with apologies to |
| Fast-stuff: (717) 396-9897 | A. A. Milne |
>I have used the comma operator a number of times with these new "modern"
>system calls (MACH) that don't return the value you really want but instead
>an error indicator (why not have "legal" and "illegal" values like Unix
>always did?) This is really ugly but puts the call into if statements
>and assignments so I am not confused as to whether the result is used
>anywhere else:
The problem with "legal" and "illegal" values is that sometimes there
is no illegal value, and if there is there's only one (NULL). So in
order to know what your error was you have to look at some external
variable errno, which is considered not quite up to the modern modular
programming paradigm. The fact that "Unix always did" does not mean
it's good but just that when Unix was designed, no one bothered about
proper error handling.
> extern errorcode sysfunction(int *returnvalue,args...);
> ...
> int junk;
> if (sysfunction(&junk,1,2,3),junk) {...
Note that this piece of code does not test whether sysfunction()
failed but only whether junk!=0. sysfunction() returns an error code
so that you can simply go
if (sysfunction(&junk,1,2,3) == OK_CODE)
... do what you want with junk etc ...
--
Nick Ruprecht
Institut fuer Informatik der Universitaet Freiburg, Germany
(rupr...@informatik.uni-freiburg.de)
Nope, you're wrong, (I don't wanna be picky on this.) Read K&R2 page 40:
`External and static variables are initialized to zero by default.
Automatic variables for which there is no explicit initializer have
undefined (i.e. garbage) values.'
regards,
Jos (j...@and.nl)
ps Dik, I like your little C-gem. Did you write it?
Well, if you do, at least give the reader of your code
a fair warning by using all UPPER CASE for the macro.
#define MYMAC(a) (foo(a), bar(a))
The upper case letters are a clear warning:
"This is a macro. The argument may be evaluated zero,
once or many times."
printf("MYMAC(a++) returned %d\n", MYMAC(a++));
printf("a ended up as %d in main\n", a);
printf("This should not be too surprising.\n");
printf("You have been warned!\n");
--
-----------------------------------------------------------------------------
| Johan Bengtsson, Telia Research AB, Aurorum 6, S-951 75 Lulea, Sweden |
| Email: j...@lulea.telesoft.se; Voice: (+46) 92075471; Fax: (+46) 92075490 |
-----------------------------------------------------------------------------
#define DEBUG_MSG !debug ? 0 : printf
Twisted, but it works...
Amanda Walker ama...@visix.com
Visix Software Inc. ...!uunet!visix!amanda
--
"On the whole human beings want to be good, but not too good and not quite all
the time." --George Orwell.
I've always believed that it should be CARVED IN STONE that one should
always, always, always, without exception, code macros so that arguments
are evaluated EXACTLY ONCE and ONLY ONCE. Not less than once and not
more than once.
The assert macro violates this condition. It would be kinda
pointless if it didn't. I've even been hosed by trying to
do work inside an assert macro argument. How embarassing.
-david
Ah, how quickly we forget. In the *original* Unix, the returned status
from a system call comprised an error/okay bit and a value word that
contained either a specific error code or the return value.
The odious "errno" was added when C came along.
Yes, remember, the first Unixes were written in assembler. The error/okay
bit was the C (carry) bit of the condition codes; the pdp11 assembler had
special bes (Branch on Error Set) and bec (Branch on Error Clear) mnemonics,
synonyms for bcs and bcc. The error code or returned value was in r0, with
later two-word returned values (e.g. from lseek) using r1 as well.
--
Programming graphics in X is like | Henry Spencer @ U of Toronto Zoology
finding sqrt(pi) using Roman numerals. | he...@zoo.toronto.edu utzoo!henry
>I use it all the time (especially in IOCCC entries :-) ), either as in the
>above (except without the spaces :-)), or in a more complex thing, like
> while(i++<j)
> x=some_action(i),
> y=other_result(i);
> do_something(x,y),
> etc, etc;
> the_next_bit();
>It somehow looks better without braces. The way it is written clearly
>indicates the structure, and IMHO it doesn't matter whether the punctuation
>marks are commas or semicolons, or whether or not there are braces. It does
Well unfortunately for you it _does_ matter to the C compiler! What you
are saying is that the next maintainer of your programs has to _read_
_carefully_and_understand_ every single line you write in order to
perform any reliable work on your program. Now consider:
while(i++<j) {
x=some_action(i),
y=other_result(i);
do_something(x,y),
etc, etc;
}
the_next_bit();
The ground rules: NEVER NEVER NEVER NEVER omit the B____Y braces!!!!!!
ALWAYS put an open brace after the while (if etc.) closing parenthesis,
ALWAYS indent, ALWAYS return to the preceding indentation level with a
'}', and ALWAYS indent by exactly the same amount.
NOW, the meaning of the code can be reliably inferred by studying it
A LINE AT A TIME! HAve I forgotten a brace? No, because directly under
the while I see one. Even if there are ten pages between the while and
the }, who cares? I am returning to a previous indentation level, so
a brace MUST be placed. And so on.
BTW, did you notice I put one ';' in your code? No? I rest my case.
--
Regards,
Ron House. (s64...@zeus.usq.edu.au)
(By post: Info Tech, U.C.S.Q. Toowoomba. Australia. 4350)
>[...] the first Unixes were written in assembler. The error/okay bit
>was the C (carry) bit of the condition codes [...]. The error code
>or returned value was in r0, with later two-word returned values
>(e.g. from lseek) using r1 as well.
System calls still work that way in 4.3BSD (and probably later). But
the access functions in the standard C library move the error code to
errno and set the return value to -1 when the carry bit is set.
If someone is feeling very modular, they can make an alternative
library where each call (system or not) returns a thingie like
struct sys_sig_return {
int errno;
void (*result)(int);
}
(with names changed to fit into their specific weird scheme). Maybe
there ought to be a 'success' flag, with the value of the errno member
unspecified for the normal (non-error) return case, but we may just as
well use an errno member value of zero as the flag. The value of the
result member can be unspecified in the error case.
It would be a little more cumbersome to use this style of library, but
if you practise paranoid programming the difference might be very
small --- mostly a matter of multiple variables to hold the different
return types. (And it might inspire people to check for errors in more
situations because some convenient shortcuts disappear.)
--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark [uunet!]mcsun!diku!thorinn
Warning: This article may contain unmarked humour. tho...@diku.dk
Yup.
Or as someone's .sig says: "Professional programming is paranoid programming."
The rest of the system IS out to get both you AND your code!
--
John Baldwin jo...@searchtech.com
search technology, inc. uupsi!srchtec!johnb
4725 peachtree corners cir., ste 200 jo...@srchtec.uucp
norcross, georgia 30092
Now that's one macro definition that you better *not* wrap parentheses
around!
|>Twisted, but it works...
|>
|>Amanda Walker ama...@visix.com
|>Visix Software Inc. ...!uunet!visix!amanda
==================
Chris Volpe
G.E. Corporate R&D
vol...@crd.ge.com
It may be true that assert() on many current systems does not obey this
rule, however it's worth pointing out that both the ANSI 'C' standard and
POSIX.1 require that assert() evaluates its argument exactly once.
The only exemptions these standards make is that getc() and putc() are
allowed to evaluate their stream arguments more than once. There is no
exemption for assert().
--
Geoff Clare <g...@root.co.uk> (USA UUCP-only mailers: ...!uunet!root.co.uk!gwc)
UniSoft Limited, London, England. Tel: +44 71 729 3773 Fax: +44 71 729 3273
It may be true that assert() on many current systems does not obey
this rule, however it's worth pointing out that both the ANSI 'C'
standard and POSIX.1 require that assert() evaluates its argument
exactly once.
That happens not to be the case. From the ANSI C standard:
4.2 Diagnostics <assert.h>
If NDEBUG is defined as a macro name at the point in the source
file where <assert.h> is included, the assert macro is defined
simply as
#define assert(ignore) ((void) 0)
The assert macro shall be implemented as a macro, not as an actual
function. If the macro definition is suppressed in order to access
an actual function, the bahavior is undefined.
--
"The best way to protect your liberty is to protect the liberty of others.
Liberty is not a pie; it's an insurance program." -- Carl Kadie
Tim McDaniel Applied Dynamics Int'l.; Ann Arbor, Michigan, USA
Internet: mcda...@adi.com UUCP: {uunet,sharkey}!amara!mcdaniel
>In article <33...@root44.co.uk> g...@root.co.uk (Geoff Clare) writes:
> It may be true that assert() on many current systems does not obey
> this rule, however it's worth pointing out that both the ANSI 'C'
> standard and POSIX.1 require that assert() evaluates its argument
> exactly once.
>That happens not to be the case.
My apologies. I made the mistake of believing POSIX.3.1 without checking
POSIX.1 or the C Standard to make sure it was right. It just goes to
show that even though POSIX.3.1 is starting to reach maturity, there are
still fundamental errors going unnoticed by balloters.
POSIX.3.1 also makes the mistake of requiring setjmp() and sigsetjmp()
macros to evaluate their arguments exactly once.
In article <MCDANIEL.9...@dolphin.adi.com>,
mcda...@adi.com (Tim McDaniel) writes:
>That happens not to be the case. From the ANSI C standard:
> 4.2 Diagnostics <assert.h>
> If NDEBUG is defined as a macro name at the point in the source
> file where <assert.h> is included, the assert macro is defined
> simply as
> #define assert(ignore) ((void) 0)
> The assert macro shall be implemented as a macro, not as an actual
> function. If the macro definition is suppressed in order to access
> an actual function, the behavior is undefined.
I think you've missed the point of assert(). It is true that assert()
evaluates its argument exactly once, if NDEBUG has not been #defined when
<assert.h> was #included. Otherwise, assert() ignores its argument
completely. Tim seems to imply that the argument must be calculated
regardless.
assert() is meant to be a temporary-use debugging tool. That implies
that the program should work as though the assert()s are removed (_not_
_replaced_.) It follows (to me, anyway) that the assert() argument must
not contain any side effects (from operators or pointer-to-non-const
passing.) Admittedly, this makes the "exactly one evaluation" requirement
a little redundant.
--
[ Darren Morby Revenue Canada Taxation ]
[ {uunet|lsuc|fts1}!revcan!darren 400 Cumberland St, Rm 3052 ]
[ Phone (613)957-9281 Ottawa, ONT K1A 0L8 ]
I failed to recognize the other reasons for "exactly one evaluation,"
the most important of which is time. No one wants too much time spent
on an assert(). I apologize for this oversight.
In article <1991Oct15....@revcan.RCT.CA> dar...@revcan.RCT.CA
(Darren Morbey) writes:
Tim seems to imply that the argument must be calculated regardless.
In the quote above, I fail to see where I implied anything. In fact,
I seem to have stated the exact opposite. The quote from 4.2.1.1
applies only if NDEBUG is not defined at the point of inclusion. The
ANSI C committee might have worded it a bit better, I suppose.
In any event, Darren and I agree that assert() need not evaluate its
argument, and therefore that its argument should not cause
side-effects.