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

Why don't C comments nest?

70 views
Skip to first unread message

Aron Packer

unread,
Nov 11, 2011, 2:21:06 PM11/11/11
to
Hi all,

(Apologies if this is in a FAQ somewhere, I couldn't find anything).

Almost every time I do any significant amount of coding in C or C++, I
end up wishing C-style comments would nest. It would make rapid
debugging much more convenient (vs. #if 0/#endif or editor macros).

Anyway, was this an explicit design decision, or some sort of historical
artifact? (e.g. too expensive to parse at the time). What other sorts of
reasons might exist against nesting comments?

Thanks!

James Kuyper

unread,
Nov 11, 2011, 2:31:54 PM11/11/11
to
The Rationale (Revision 5.1.0 April-2003) says:
> The C89 Committee considered proposals to allow comments to nest. The main argument for
> nesting comments is that it would allow programmers to “comment out” code. The C89
> Committee rejected this proposal on the grounds that comments should be used for adding
> documentation to a program, and that preferable mechanisms already exist for source code
> exclusion. For example,
>
> #if 0
> /* code to be excluded */
> #endif
>
> Preprocessing directives such as this prevent the enclosed code from being scanned by later
> translation phases. Bracketed material can include comments and other nested regions of
> bracketed code.
>
> Another way of accomplishing these goals is with an if statement:
> if (0) {
> /* code to be excluded */
> }
>
> Many modern compilers will generate no code for this if statement.


nroberts

unread,
Nov 11, 2011, 2:25:25 PM11/11/11
to
Well, it does make parsing a little easier. If you try to write a C-
comment remover, which I believe is an exercise in K&R, you'd probably
see why.

Kaz Kylheku

unread,
Nov 11, 2011, 3:11:12 PM11/11/11
to
On 2011-11-11, Aron Packer <at...@rightthing.invalid> wrote:
> Hi all,
>
> (Apologies if this is in a FAQ somewhere, I couldn't find anything).
>
> Almost every time I do any significant amount of coding in C or C++, I
> end up wishing C-style comments would nest. It would make rapid
> debugging much more convenient (vs. #if 0/#endif or editor macros).

Rapid meaning, what you save a few keystrokes over #if 0?

> Anyway, was this an explicit design decision, or some sort of historical
> artifact? (e.g. too expensive to parse at the time). What other sorts of
> reasons might exist against nesting comments?

Consideration 1:

In order for comments to be suitable as a feature for commenting out code,
the language has to be defined differently. Firstly, /* and */ have to be
tokens. Secondly, the "commented out" material between the /* and */ tokens has
to also be delimited into tokens.

This way, for instance, the following will not break:

/* char *comment_end = "/*"; */

Here, "/*" is embedded in a string literal token and so loses
the comment-closing meaning.

If you don't have this kind of robustness, there is no point in allowing nested
comments.

Either solve the embedding problem 100% or don't bother.

Note that if you allow only tokens between /* and */, then it becomes
more difficult to write comments, which cannot be freeform text.

The #if 0 directive solves the embedding problem, because material which is
skipped by the preprocessor is still decomposed into tokens.
This is why we don't use it for writing comments.

The upshot is that /* */ is for writing comments and #if ... #endif
is for "compiling out" code you don't want.

Consideration 2:

Nesting C comments are not recognizeable by a finite automaton (regular
language). They require a push-down automaton or counter: something
to keep track of the nesting levels so every open /* is balanced
by a closing */.

This is a minor thing but it does mean that in a lexical analyzer generator
based on a tool like lex, you have to write dedicated code for C comments.
(This is sometimes done in practice anyway even for non-nesting comments,
because the regex for C comments is convoluted and ugly if the regex language
does not support advanced operators like a non-greedy Kleene star, or
complement.)

It is nevertheless a useful fact that C can be tokenized purely with regexes,
ugly or not, including the recognition of comments.

BartC

unread,
Nov 11, 2011, 3:28:54 PM11/11/11
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201111111...@kylheku.com...
> On 2011-11-11, Aron Packer <at...@rightthing.invalid> wrote:
>> Hi all,
>>
>> (Apologies if this is in a FAQ somewhere, I couldn't find anything).
>>
>> Almost every time I do any significant amount of coding in C or C++, I
>> end up wishing C-style comments would nest. It would make rapid
>> debugging much more convenient (vs. #if 0/#endif or editor macros).
>
> Rapid meaning, what you save a few keystrokes over #if 0?
>
>> Anyway, was this an explicit design decision, or some sort of historical
>> artifact? (e.g. too expensive to parse at the time). What other sorts of
>> reasons might exist against nesting comments?
>
> Consideration 1:
>
> In order for comments to be suitable as a feature for commenting out
> code,
> the language has to be defined differently. Firstly, /* and */ have to be
> tokens. Secondly, the "commented out" material between the /* and */
> tokens has
> to also be delimited into tokens.

I don't think that's necessary, but you have to consider that */ inside a
string literal, or as part of a // comment, may cause problems.

> This way, for instance, the following will not break:
>
> /* char *comment_end = "/*"; */

> Here, "/*" is embedded in a string literal token and so loses
> the comment-closing meaning.

You mean "*/"? In which case you can't even write it whether you have nested
comments or not:

/* char *comment_end = "*/"; */

I've programmed nested comments in lexers before, and most of the time they
work fine. (It seems to be mostly commenting-out blocks of lexer code, which
is full of literals and comments to do with comment-processing, that cause
problems.)

> If you don't have this kind of robustness, there is no point in allowing
> nested
> comments.
> Either solve the embedding problem 100% or don't bother.

The above example (and a there are a few more) show that even normal
comments aren't 100% robust, so what's the difference? Nobody's going to be
forcing anyone to make use of them.

>
> Note that if you allow only tokens between /* and */, then it becomes
> more difficult to write comments, which cannot be freeform text.
>
> The #if 0 directive solves the embedding problem, because material which
> is

Perhaps have #comment ... #end then


> The upshot is that /* */ is for writing comments and #if ... #endif
> is for "compiling out" code you don't want.

Suppose the code you want to comment out is the middle of a line, which is
already using /*...*/ ?

--
Bartc


Keith Thompson

unread,
Nov 11, 2011, 4:16:38 PM11/11/11
to
"BartC" <b...@freeuk.com> writes:
> "Kaz Kylheku" <k...@kylheku.com> wrote in message
> news:201111111...@kylheku.com...
[...]
>> The #if 0 directive solves the embedding problem, because material which
>> is
>
> Perhaps have #comment ... #end then

Hmm? What problem would #comment ... #end solve that #if 0 ... #endif
doesn't already solve?

>> The upshot is that /* */ is for writing comments and #if ... #endif
>> is for "compiling out" code you don't want.
>
> Suppose the code you want to comment out is the middle of a line, which is
> already using /*...*/ ?

Well then I guess you've got a bit of a problem. But I don't think I've
evern run into that situation.

Let's see if I can come up with a plausible example.

some_func(10 /* param1 */, 20 /* param2 */, 30 /* param3 */);

The comments are there to show the names of the actual parameters,
without which "some_func(10, 20, 30);" isn't nearly as clear.

Then some_func is changed so it only takes 2 parameters, but you want to
keep the information about the 3rd one in the source for some reason.

First, consider whether that's really worth doing. You can just delete
the third argument altogether:

some_func(10 /* param1 */, 20 /* param2 */);

and if you need to see the 3-argument version of the call, you can just
look in your source control system. (You *are* using one, right?)

But ok, let's say there's a good reason to keep the original version as
a comment. Here's how I might do it:

#if 0
some_func(10 /* param1 */, 20 /* param2 */, 30 /* param3 */);
#else
some_func(10 /* param1 */, 20 /* param2 */);
#endif

Any definition of how comments work (nesting vs. non-nesting,
single-line vs. end-of-line vs. partial-line vs. multi-line, etc.) is
going to be inconvenient for some purposes. None of these
inconveniences are insurmountable.

And of course changing the rules now would break existing code. I've
seen code that specifically depends on the fact that /**/ comments
*don't* nest.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

James Kuyper

unread,
Nov 11, 2011, 4:28:13 PM11/11/11
to
On 11/11/2011 04:16 PM, Keith Thompson wrote:
> "BartC" <b...@freeuk.com> writes:
...
>> Suppose the code you want to comment out is the middle of a line, which is
>> already using /*...*/ ?
>
> Well then I guess you've got a bit of a problem. But I don't think I've
> evern run into that situation.
>
> Let's see if I can come up with a plausible example.
>
> some_func(10 /* param1 */, 20 /* param2 */, 30 /* param3 */);
>
> The comments are there to show the names of the actual parameters,
> without which "some_func(10, 20, 30);" isn't nearly as clear.
>
> Then some_func is changed so it only takes 2 parameters, but you want to
> keep the information about the 3rd one in the source for some reason.
>
> First, consider whether that's really worth doing. You can just delete
> the third argument altogether:
>
> some_func(10 /* param1 */, 20 /* param2 */);
>
> and if you need to see the 3-argument version of the call, you can just
> look in your source control system. (You *are* using one, right?)
>
> But ok, let's say there's a good reason to keep the original version as
> a comment. Here's how I might do it:
>
> #if 0
> some_func(10 /* param1 */, 20 /* param2 */, 30 /* param3 */);
> #else
> some_func(10 /* param1 */, 20 /* param2 */);
> #endif

My preference is

some_func(10 /* param1 */, 20 /* param2 */
#if 0
, 30 /* param3 */
#endif
);

But I can understand why some might consider that ugly.


Keith Thompson

unread,
Nov 11, 2011, 4:54:46 PM11/11/11
to
James Kuyper <james...@verizon.net> writes:
> On 11/11/2011 04:16 PM, Keith Thompson wrote:
[...]
>> But ok, let's say there's a good reason to keep the original version as
>> a comment. Here's how I might do it:
>>
>> #if 0
>> some_func(10 /* param1 */, 20 /* param2 */, 30 /* param3 */);
>> #else
>> some_func(10 /* param1 */, 20 /* param2 */);
>> #endif
>
> My preference is
>
> some_func(10 /* param1 */, 20 /* param2 */
> #if 0
> , 30 /* param3 */
> #endif
> );
>
> But I can understand why some might consider that ugly.

If a comma were permitted after the last parameter declaration, you
could just write:

some_function(10 /* param1 */,
20 /* param2 */,
#if 0
30 /* param3 */,
#endif
);

C99 changed the syntax to permit a trailing comma in an enum
declaration. It would have made sense to permit a trailling
comma for *any* comma-separated list. (Probably not for the comma
operator, though.)

BartC

unread,
Nov 11, 2011, 5:14:40 PM11/11/11
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnobwi7...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:
>> "Kaz Kylheku" <k...@kylheku.com> wrote in message
>> news:201111111...@kylheku.com...
> [...]
>>> The #if 0 directive solves the embedding problem, because material which
>>> is
>>
>> Perhaps have #comment ... #end then

> Hmm? What problem would #comment ... #end solve that #if 0 ... #endif
> doesn't already solve?

It's more self-explanatory than #if 0

>> Suppose the code you want to comment out is the middle of a line, which
>> is
>> already using /*...*/ ?
>
> Well then I guess you've got a bit of a problem. But I don't think I've
> evern run into that situation.
>
> Let's see if I can come up with a plausible example.

The problem is placing unnecessary restrictions on how C code is laid out.

Insisting on #if 0 means imposing a line-oriented structure, while C is
supposed to be free-format.

Besides, any example anyone comes up with, can be rewritten to use multiple
lines that would allow the use of #if 0. If which case, why bother having
/*...*/ comments at all?

The advantage of /*...*/ is starting and/or ending the comment in the middle
of a line. If that is desirable, why shouldn't one be able to do it on a
section of code (which could span multiple lines) which happens to already
have a comment in there?

Maybe there are several existing comments, some can be whole lines and some
partial. Or it's a massive bit of code and it may not be easy to check
whether there are comments there or not! But it shouldn't be necessary to
care.

--
Bartc

Ian Collins

unread,
Nov 11, 2011, 5:20:58 PM11/11/11
to
On 11/12/11 09:28 AM, BartC wrote:
> "Kaz Kylheku"<k...@kylheku.com> wrote:
>
>> The upshot is that /* */ is for writing comments and #if ... #endif
>> is for "compiling out" code you don't want.
>
> Suppose the code you want to comment out is the middle of a line, which is
> already using /*...*/ ?

Check in, remove code, compile, test and if required, revert.

--
Ian Collins

Ben Pfaff

unread,
Nov 11, 2011, 5:35:38 PM11/11/11
to
"BartC" <b...@freeuk.com> writes:

> Besides, any example anyone comes up with, can be rewritten to use multiple
> lines that would allow the use of #if 0. If which case, why bother
> having /*...*/ comments at all?

#if 0
Because this won't compile.
#endif
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

Phil Carmody

unread,
Nov 11, 2011, 5:40:58 PM11/11/11
to
That example wouldn't demonstrate nesting. I prefer the "/*" example,
as, with nesting, you can't use the final */ to close the comment, only
to decrease its comment nesting to 1.

Phil
--
Unix is simple. It just takes a genius to understand its simplicity
-- Dennis Ritchie (1941-2011), Unix Co-Creator

Keith Thompson

unread,
Nov 11, 2011, 6:14:01 PM11/11/11
to
"BartC" <b...@freeuk.com> writes:
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnobwi7...@nuthaus.mib.org...
>> "BartC" <b...@freeuk.com> writes:
>>> "Kaz Kylheku" <k...@kylheku.com> wrote in message
>>> news:201111111...@kylheku.com...
>> [...]
>>>> The #if 0 directive solves the embedding problem, because material which
>>>> is
>>>
>>> Perhaps have #comment ... #end then
>
>> Hmm? What problem would #comment ... #end solve that #if 0 ... #endif
>> doesn't already solve?
>
> It's more self-explanatory than #if 0

So use #ifdef SOME_MEANINGFUL_IDENTIFIER, and don't provide a definition
for that identifier.

>>> Suppose the code you want to comment out is the middle of a line, which
>>> is
>>> already using /*...*/ ?
>>
>> Well then I guess you've got a bit of a problem. But I don't think I've
>> evern run into that situation.
>>
>> Let's see if I can come up with a plausible example.
>
> The problem is placing unnecessary restrictions on how C code is laid out.
>
> Insisting on #if 0 means imposing a line-oriented structure, while C is
> supposed to be free-format.
>
> Besides, any example anyone comes up with, can be rewritten to use multiple
> lines that would allow the use of #if 0. If which case, why bother having
> /*...*/ comments at all?

Because /*...*/ comments are more convenient in many cases.

(Personally, I wouldn't mind having just // comments and no /*...*/
comments, but of course we can't change that now. There are plenty of
languages that only have end-of-lime comments.)

> The advantage of /*...*/ is starting and/or ending the comment in the middle
> of a line. If that is desirable, why shouldn't one be able to do it on a
> section of code (which could span multiple lines) which happens to already
> have a comment in there?

Because nothing is perfect, and you can't have everything.

> Maybe there are several existing comments, some can be whole lines and some
> partial. Or it's a massive bit of code and it may not be easy to check
> whether there are comments there or not! But it shouldn't be necessary to
> care.

I have no doubt that the syntax of C comments could be tweaked in some
way that would be more to your liking. Any such change would result in
something that's less to someone else's liking. I don't suggest that
your preferences are less important than someone else's; the deciding
factor has to be backward compatibility.

Come up with a proposed change that (a) does what you want, and (b)
doesn't break existing code, and we can discuss it. (But the current
system isn't sufficiently broken that any such change is likely to be
adopted.)

BartC

unread,
Nov 11, 2011, 7:10:16 PM11/11/11
to


"Ben Pfaff" <b...@cs.stanford.edu> wrote in message
news:874nya5...@blp.benpfaff.org...
> "BartC" <b...@freeuk.com> writes:
>
>> Besides, any example anyone comes up with, can be rewritten to use
>> multiple
>> lines that would allow the use of #if 0. If which case, why bother
>> having /*...*/ comments at all?
>
> #if 0
> Because this won't compile.
> #endif

OK, so lines between #if 0 and #endif are tokenised (as I found out earlier)
and need to contain well-formed char/string literals and ordinary comments,
even if it doesn't care about other tokens and about any syntax.

(Which also means it might be unusable for some kinds of multi-line
comments, where you want to temporarily comment-out a half-finished block of
code where some tokens are not complete. Although there is the same problem
with enclosing the block in a /*...*/ comment when there is an open /*...*/
comment inside.)

I would have expected #if 0 to completely ignore any lines that didn't start
with #.

--
Bartc

BartC

unread,
Nov 11, 2011, 7:37:23 PM11/11/11
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:ln39du6...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:

>> Besides, any example anyone comes up with, can be rewritten to use
>> multiple
>> lines that would allow the use of #if 0. If which case, why bother having
>> /*...*/ comments at all?
>
> Because /*...*/ comments are more convenient in many cases.
>
> (Personally, I wouldn't mind having just // comments and no /*...*/
> comments, but of course we can't change that now. There are plenty of
> languages that only have end-of-lime comments.)

// comments aren't too bad, other than problems with imposing
line-orientation on the source code (so breaking a line inside a // comment
causes a problem, and so does joining a //-line to a non-// one).

And they behave much better with nested comments.

> I have no doubt that the syntax of C comments could be tweaked in some
> way that would be more to your liking.

Don't worry about me; I don't use C enough for it to be that important.

I'm just saying that /*...*/ can be made to nest without any serious
problems, most of the time...; no new syntax is needed.

(I've programmed nested comments for other languages, and they work fine;
mostly I used {...}, which would be problematic for C, and have experimented
with \...\ and {/.../} (which frees up { and }). However 99% of the time I
use //-like comments to end-of-line, but with a single character, such as !,
# and \.

> Any such change would result in
> something that's less to someone else's liking.

(Ideally you would just tell an editor to comment/uncomment some highlighted
text, and it would just do it. Nested comments are still important, and
maybe it could even fix-up any troublesome characters, such as a stray */,
that might cause a problem. In this case the actual comment syntax becomes
less critical.)

--
Bartc

Message has been deleted

Eric Sosman

unread,
Nov 11, 2011, 8:21:24 PM11/11/11
to
On 11/11/2011 5:14 PM, BartC wrote:
> [...]
> Besides, any example anyone comes up with, can be rewritten to use multiple
> lines that would allow the use of #if 0. If which case, why bother
> having /*...*/ comments at all?

Because the text inside /*...*/ can be anything at all except */.

strcat(p, "'"); /* can't use " here */

If you want comments to nest and *not* to be tripped up by examples
like Kaz' `/* char *comment_end = "/*"; */', then you need to insist
that the comment's content be lex-able, and comments like the one in
my example would become impossible.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Kaz Kylheku

unread,
Nov 11, 2011, 11:29:19 PM11/11/11
to
On 2011-11-11, BartC <b...@freeuk.com> wrote:
> "Kaz Kylheku" <k...@kylheku.com> wrote in message
>> This way, for instance, the following will not break:
>>
>> /* char *comment_end = "/*"; */
>
>> Here, "/*" is embedded in a string literal token and so loses
>> the comment-closing meaning.
>
> You mean "*/"? In which case you can't even write it whether you have nested
> comments or not:

That's my point. You can't write it without nested comments, but nested
comments don't fix anything.

>> Note that if you allow only tokens between /* and */, then it becomes
>> more difficult to write comments, which cannot be freeform text.
>>
>> The #if 0 directive solves the embedding problem, because material which
>> is
>
> Perhaps have #comment ... #end then

That's a useless syntactic sugar for #if 0; furthermore, it's badly
named since this feature is not for commenting. Your "comment" has
to be written in valid C preprocessor tokens.

Really, do you need to be able to invoke undefined behavior in comments? :)

> Suppose the code you want to comment out is the middle of a line, which is
> already using /*...*/ ?

There is this:

C89:

#define IGN(X)

IGN( foo() );

void bar(IGN( const ) int *ptr)
{
}

Now, an unparenthesized comma doesn't work, e,g. IGN(A, B).

C99 varidic macros to the rescue:

#define IGN(...)

struct x y = { 1, 2 IGN( , 3, 4 ) };

Or you could just edit the darn code. Remove the inner /* */ and add the outer
ones. There are few enough people working in C, and out of those few enough who
have this problem, that it's not some kind of wide-spread economic problem.

BartC

unread,
Nov 12, 2011, 5:54:37 AM11/12/11
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201111112...@kylheku.com...
> On 2011-11-11, BartC <b...@freeuk.com> wrote:

>> Perhaps have #comment ... #end then
>
> That's a useless syntactic sugar for #if 0; furthermore, it's badly
> named since this feature is not for commenting. Your "comment" has
> to be written in valid C preprocessor tokens.

That was before I realised that #if 0 didn't work as I expected, ie. ignore
everything except what was necessary to find a matching #endif.

--
Bartc

BartC

unread,
Nov 12, 2011, 6:10:09 AM11/12/11
to


"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
news:j9khmm$2qa$1...@dont-email.me...
> On 11/11/2011 5:14 PM, BartC wrote:

> strcat(p, "'"); /* can't use " here */

Sorry I don't understand your point here.

> If you want comments to nest and *not* to be tripped up by examples
> like Kaz' `/* char *comment_end = "/*"; */', then you need to insist
> that the comment's content be lex-able, and comments like the one in
> my example would become impossible.

But if someone wants to write a /* ... */ comment then they will be tripped
up by anything containing a */:

// */gobbledygook/*

The above is fine (maybe they intended the comment to be bold/italic on
Usenet). Now comment out the section using /*...*/:

/*
// */gobbledygook/*
*/

Now it no longer compiles (not unless gobbledygook is a valid macro).

So /*...*/ comments are flawed whether they are nested or not. Since they
are still widely used despite this flaw, I can't see why the similarly
flawed nested ones can't also have been in use from the start (I agree
introducing them now might throw up a few odd errors).

--
Bartc

Willem

unread,
Nov 12, 2011, 7:07:51 AM11/12/11
to
Keith Thompson wrote:
) If a comma were permitted after the last parameter declaration, you
) could just write:
)
) some_function(10 /* param1 */,
) 20 /* param2 */,
) #if 0
) 30 /* param3 */,
) #endif
) );

Which is why I have changed my preference to writing this:

some_function(10 /* param1 */
,20 /* param2 */
#if 0
,30 /* param3 */
#endif
);

And not only in C, but in almost any language.

The point is that this plays a lot nicer with revision control systems,
because adding or removing an argument is a 1-line change, whereas in the
other case it can potentially change the previous line as well.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Eric Sosman

unread,
Nov 12, 2011, 8:11:12 AM11/12/11
to
On 11/12/2011 6:10 AM, BartC wrote:
>
>
> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
> news:j9khmm$2qa$1...@dont-email.me...
>> On 11/11/2011 5:14 PM, BartC wrote:
>
>> strcat(p, "'"); /* can't use " here */
>
> Sorry I don't understand your point here.

See below.

>> If you want comments to nest and *not* to be tripped up by examples
>> like Kaz' `/* char *comment_end = "/*"; */', then you need to insist
>> that the comment's content be lex-able, and comments like the one in
>> my example would become impossible.
>
> But if someone wants to write a /* ... */ comment then they will be tripped
> up by anything containing a */:

... which Kaz' example does not. Repeat: Kaz' example does not
contain a */ inside the comment. Look more closely.

His example works fine in today's C, but would get into trouble
in a C where comments nested. Why? Because you're on the horns of
a dilemma:

- You can see the quoted /* as the start of a nested comment,
causing you to interpret the */ as the end of that nested
comment,

or

- You must lex the internals of the comment to recognize that
that "/*" is a string literal and not the start of an inner
comment.

If you take the first course, then the */ ends the internal comment
but leaves the external comment still alive, still eating all the
rest of the source file. If you take the second, then you must
disallow comments of the kind I illustrated above, because your
lexer will trip over the unmatched ' and/or " characters.

--
Eric Sosman
eso...@ieee-dot-org.invalid

BartC

unread,
Nov 12, 2011, 8:57:41 AM11/12/11
to
"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
news:j9lrai$mm$1...@dont-email.me...
> On 11/12/2011 6:10 AM, BartC wrote:

>> But if someone wants to write a /* ... */ comment then they will be
>> tripped
>> up by anything containing a */:
>
> ... which Kaz' example does not. Repeat: Kaz' example does not
> contain a */ inside the comment. Look more closely.

Yes I know it doesn't. And I gave a counter-example which looked like this:

/* char *comment_end = "*/"; */

(which also happens to match the variable more accurately, but that's
another matter...)

> rest of the source file. If you take the second, then you must
> disallow comments of the kind I illustrated above, because your
> lexer will trip over the unmatched ' and/or " characters.

And as things are now, we must disallow comments like my example.

I can't see why one is any worse than the other.

--
Bartc

Stephen Sprunk

unread,
Nov 12, 2011, 9:21:27 AM11/12/11
to
On 11-Nov-11 15:54, Keith Thompson wrote:
> C99 changed the syntax to permit a trailing comma in an enum
> declaration. It would have made sense to permit a trailling
> comma for *any* comma-separated list. (Probably not for the comma
> operator, though.)

Why not? If ";" is a valid statement, then why shouldn't ",;" be valid?

S


--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

Lauri Alanko

unread,
Nov 12, 2011, 9:29:11 AM11/12/11
to
In article <j9lvd7$mn0$2...@dont-email.me>,
Stephen Sprunk <ste...@sprunk.org> wrote:
> Why not? If ";" is a valid statement, then why shouldn't ",;" be valid?

Because the comma operator separates expressions, not statements.


Lauri

Eric Sosman

unread,
Nov 12, 2011, 9:34:13 AM11/12/11
to
Would you like to be able to use a contraction like

if (p < endp) /* don't run off the end! */

in a comment? Then you don't want comments that nest.

Comments are not for suppressing blocks of code; comments are
for commentary.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Nov 12, 2011, 9:44:37 AM11/12/11
to
On 11/12/2011 9:21 AM, Stephen Sprunk wrote:
> On 11-Nov-11 15:54, Keith Thompson wrote:
>> C99 changed the syntax to permit a trailing comma in an enum
>> declaration. It would have made sense to permit a trailling
>> comma for *any* comma-separated list. (Probably not for the comma
>> operator, though.)
>
> Why not? If ";" is a valid statement, then why shouldn't ",;" be valid?

Do you think `*;' should be valid?

(If so, how many operands have been omitted? ;-)

--
Eric Sosman
eso...@ieee-dot-org.invalid
Message has been deleted
Message has been deleted

Kaz Kylheku

unread,
Nov 12, 2011, 12:51:29 PM11/12/11
to
That's true, but it does so by being a binary operator which
requires two operands.

The ; is not an operator, but a punctuator which terminates.

BartC

unread,
Nov 12, 2011, 1:17:36 PM11/12/11
to
"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
news:j9m058$sil$1...@dont-email.me...
> On 11/12/2011 8:57 AM, BartC wrote:

>> And as things are now, we must disallow comments like my example.
>>
>> I can't see why one is any worse than the other.
>
> Would you like to be able to use a contraction like
>
> if (p < endp) /* don't run off the end! */

(I still don't see what the problem would be with this example; what's
supposed to happen when that line in enclosed in another /*...*/ comment?)

> in a comment? Then you don't want comments that nest.
>
> Comments are not for suppressing blocks of code; comments are
> for commentary.

Nevertheless that's what the OP wants to do. Does the Standard specifically
tell us what content is allowed in a comment, and what is frowned upon?

--
Bartc



Robert Wessel

unread,
Nov 12, 2011, 3:09:38 PM11/12/11
to
On Sat, 12 Nov 2011 18:17:36 -0000, "BartC" <b...@freeuk.com> wrote:

>"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
>news:j9m058$sil$1...@dont-email.me...
>> On 11/12/2011 8:57 AM, BartC wrote:
>
>>> And as things are now, we must disallow comments like my example.
>>>
>>> I can't see why one is any worse than the other.
>>
>> Would you like to be able to use a contraction like
>>
>> if (p < endp) /* don't run off the end! */
>
>(I still don't see what the problem would be with this example; what's
>supposed to happen when that line in enclosed in another /*...*/ comment?)


The problem in this case is that everything starting with the
apostrophe is the (start) of a character constant, thus if you've
tokenized that by the normal C rules, the */ will be lost as part of
the contents of the character constant. (In order to be valid
lexically, you'll need a closing apostrophe someplace). Of course you
cannot use just any arbitrary string in a character constant, but
that's validated after it's been tokenized.


>> in a comment? Then you don't want comments that nest.
>>
>> Comments are not for suppressing blocks of code; comments are
>> for commentary.
>
>Nevertheless that's what the OP wants to do. Does the Standard specifically
>tell us what content is allowed in a comment, and what is frowned upon?


Yes, the second sentence of the following covers it:

"6.4.9 Comments
Except within a character constant, a string literal, or a comment,
the characters /* introduce a comment. The contents of such a comment
are examined only to identify multibyte characters and to find the
characters */ that terminate it."

Ian Collins

unread,
Nov 12, 2011, 3:11:52 PM11/12/11
to
Removing the code works as expected.

--
Ian Collins

BartC

unread,
Nov 12, 2011, 3:49:32 PM11/12/11
to


"Robert Wessel" <robert...@yahoo.com> wrote in message
news:r7ktb7ddbpsld0uac...@4ax.com...
> On Sat, 12 Nov 2011 18:17:36 -0000, "BartC" <b...@freeuk.com> wrote:
>
>>"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message

>>> if (p < endp) /* don't run off the end! */
>>
>>(I still don't see what the problem would be with this example; what's
>>supposed to happen when that line in enclosed in another /*...*/ comment?)
>
> The problem in this case is that everything starting with the
> apostrophe is the (start) of a character constant, thus if you've
> tokenized that by the normal C rules, the */ will be lost as part of
> the contents of the character constant.

OK. So the assumption is that a nested comment would tokenise it's contents.

However I don't think that's necessary. And wouldn't work anyway.

>>> Comments are not for suppressing blocks of code; comments are
>>> for commentary.
>>
>>Nevertheless that's what the OP wants to do. Does the Standard
>>specifically
>>tell us what content is allowed in a comment, and what is frowned upon?
>
>
> Yes, the second sentence of the following covers it:
>
> "6.4.9 Comments
> Except within a character constant, a string literal, or a comment,
> the characters /* introduce a comment. The contents of such a comment
> are examined only to identify multibyte characters and to find the
> characters */ that terminate it."

In other words, anything is allowed, including source code, of C or anything
else.

So the suggestion that comments shouldn't contain source code is a style
issue that shouldn't be the concern of the Standard or imposed by a
compiler.

And reading in-between the lines, everything is allowed except */, even if
the latter was inside a literal, or inside a //-comment.

The only thing needed to make nested comments possible, is to disallow /* as
well as */, unless they are there to start or terminate a comment.

That means you won't be able to have /* as part of comment text, whether by
itself or part of a literal; is that really that big a deal?

--
Bartc

BartC

unread,
Nov 12, 2011, 3:52:24 PM11/12/11
to


"Ian Collins" <ian-...@hotmail.com> wrote in message
news:9i828h...@mid.individual.net...
That's rather a drastic measure. Especially if you've just downloaded some
source code and big chunks of it have been cut out! Rather difficult to
reinstate then. Anyway suppose the commented lines are actually intended to
be read?

--
Bartc

Keith Thompson

unread,
Nov 12, 2011, 4:09:24 PM11/12/11
to
"BartC" <b...@freeuk.com> writes:
> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
> news:j9m058$sil$1...@dont-email.me...
>> On 11/12/2011 8:57 AM, BartC wrote:
>
>>> And as things are now, we must disallow comments like my example.
>>>
>>> I can't see why one is any worse than the other.
>>
>> Would you like to be able to use a contraction like
>>
>> if (p < endp) /* don't run off the end! */
>
> (I still don't see what the problem would be with this example; what's
> supposed to happen when that line in enclosed in another /*...*/ comment?)

Currently, /*...*/ comments don't nest. As a result, once the
compiler sees a /* sequence that's not inside another token (a string
literal or, rarely, a character constant), it only needs to scan
for a */ sequence, regardless of the context in which it appears.

With nesting comments, after seeing an opening /*, there are several
possible approaches:

1. Scan for /* and */ without tokenization and keep a count of the
nesting level. This causes problems if a comment contains a string
literal containing /* or */:

/* const char open_comment[] = "/*"; */

The */ at the end of the line terminates the inner comment, not the
outer one. Presumably the idea of allowing nested comments is to
make it possible to use /* and */ to comment out a chunk of code
that itself contains /*...*/ comments, but this example shows that
that still wouldn't work in all cases.

2. Tokenize everything inside /*...*/ comments, so that the compiler
can detect cases like the above and ignore comment delimiters in
commented-out string literals. But this comment from Eric's post:

if (p < endp) /* don't run off the end! */

doesn't contain a valid token sequence.

3. Define a new set of tokenization rules for use inside comments,
so that comment delimiters within string literals within comments
are ignored, but arbitrary text that doesn't necesssarily form a
valid token sequence is accepted. Note that '"' and '*/' are valid
character constants. Since the content of a comment may or may not
be some approximation of C source code, it's difficult to decide
whether a given sequence of characters that happens to include
double-quote charactes should be treated as a C string literal
or not.

And of course *any* of these changes would break existing code,
which means the odd of any of them being adopted are close to zero.

>> in a comment? Then you don't want comments that nest.
>>
>> Comments are not for suppressing blocks of code; comments are
>> for commentary.
>
> Nevertheless that's what the OP wants to do. Does the Standard specifically
> tell us what content is allowed in a comment, and what is frowned upon?

Not directly, no. But it does clearly say that /*...*/ comments don't
nest, from which one can easily infer that you can't use /*...*/ to
comment out a block of code that already contains /*...*/ comments.

And if you want to comment out a block of code, you can always insert
a // at the beginning of each line. This makes it easier to see
at a glance which lines are commented out and avoids all the above
problems. (It does require you to have a compiler that recognizes //
comments, which is an issue if you want to use strict C90 or C95 mode.)

Keith Thompson

unread,
Nov 12, 2011, 4:11:18 PM11/12/11
to
Willem <wil...@toad.stack.nl> writes:
> Keith Thompson wrote:
> ) If a comma were permitted after the last parameter declaration, you
> ) could just write:
> )
> ) some_function(10 /* param1 */,
> ) 20 /* param2 */,
> ) #if 0
> ) 30 /* param3 */,
> ) #endif
> ) );
>
> Which is why I have changed my preference to writing this:
>
> some_function(10 /* param1 */
> ,20 /* param2 */
> #if 0
> ,30 /* param3 */
> #endif
> );
>
> And not only in C, but in almost any language.
>
> The point is that this plays a lot nicer with revision control systems,
> because adding or removing an argument is a 1-line change, whereas in the
> other case it can potentially change the previous line as well.

And if you want to comment out the *first* argument?

I see your point, but personally I find that layout rather hard on
my eyes. The need to comment out a single parameter is rare enough
that I don't think it's worth it.

Keith Thompson

unread,
Nov 12, 2011, 4:13:07 PM11/12/11
to
Acid Washed China Blue Jeans <chine...@yahoo.com> writes:
> In article <201111112...@kylheku.com>, Kaz Kylheku <k...@kylheku.com>
> wrote:
>
>> > Suppose the code you want to comment out is the middle of a line, which is
>> > already using /*...*/ ?
>>
>> There is this:
>>
>> C89:
>>
>> #define IGN(X)
>>
>> IGN( foo() );
>>
>> void bar(IGN( const ) int *ptr)
>> {
>> }
>>
>> Now, an unparenthesized comma doesn't work, e,g. IGN(A, B).
>
> I just select the comment text and switch the font from Helvetica to Palatino.
> That way I can embed whatever comments I want without all these distracting /*
> */ //.

That's fine if you have a compiler that accepts source code with font
information.

Ian Collins

unread,
Nov 12, 2011, 4:22:49 PM11/12/11
to
On 11/13/11 09:52 AM, BartC wrote:
>
>
> "Ian Collins"<ian-...@hotmail.com> wrote in message
> news:9i828h...@mid.individual.net...
>> On 11/12/11 11:54 PM, BartC wrote:
>>> "Kaz Kylheku"<k...@kylheku.com> wrote in message
>>> news:201111112...@kylheku.com...
>>>> On 2011-11-11, BartC<b...@freeuk.com> wrote:
>>>
>>>>> Perhaps have #comment ... #end then
>>>>
>>>> That's a useless syntactic sugar for #if 0; furthermore, it's badly
>>>> named since this feature is not for commenting. Your "comment" has
>>>> to be written in valid C preprocessor tokens.
>>>
>>> That was before I realised that #if 0 didn't work as I expected, ie.
>>> ignore
>>> everything except what was necessary to find a matching #endif.
>>
>> Removing the code works as expected.
>
> That's rather a drastic measure. Especially if you've just downloaded some
> source code and big chunks of it have been cut out!

But why would they have been cut out if they were required? Blocks of
code usually get commented out during development and this can be
managed by version control, or an IDE.

> Rather difficult to
> reinstate then. Anyway suppose the commented lines are actually intended to
> be read?

They could be commented out with //

--
Ian Collins

Keith Thompson

unread,
Nov 12, 2011, 4:42:01 PM11/12/11
to
"BartC" <b...@freeuk.com> writes:
[...]
> OK. So the assumption is that a nested comment would tokenise it's contents.
>
> However I don't think that's necessary. And wouldn't work anyway.

[big snip]

> That means you won't be able to have /* as part of comment text, whether by
> itself or part of a literal; is that really that big a deal?

It would break existing code.

If you're advocating a change to the C language, the fact that it
would break existing code means such a change will not be adopted.

If you're talking about a C-like language in which comments nest,
then you're not talking about C.

Which is it?

Kaz Kylheku

unread,
Nov 12, 2011, 4:44:57 PM11/12/11
to
On 2011-11-12, BartC <b...@freeuk.com> wrote:
> "Robert Wessel" <robert...@yahoo.com> wrote in message
>> "6.4.9 Comments
>> Except within a character constant, a string literal, or a comment,
>> the characters /* introduce a comment. The contents of such a comment
>> are examined only to identify multibyte characters and to find the
>> characters */ that terminate it."
>
> In other words, anything is allowed, including source code, of C or anything
> else.

No, because the formal language allowed within the comment excludes the
digraph */ which may occur in the source code of C, inside a string
literal, as part of a comment, or inside a // comment.

> So the suggestion that comments shouldn't contain source code is a style
> issue that shouldn't be the concern of the Standard or imposed by a
> compiler.

It's more than a style issue; it's a formal language issue. Comments can only
contain a subset of the possible set of C strings.

It is useful that you can have a subset of C within comments, for instance,
coding examples. They just can't have /*...*/ comments of their own, which is
fine since they are already inside a comment which can explain everything.

A mechanism for commenting out arbitrary code must be robust, period. This way
it can be applied to a 50,000 line piece of source code without worry that
anything breaks.

#if 0 ... #endif satisfies that requirement.

For excluding small ranges of text not confined entire lines,
a variadic macro which expands to nothing works great:

#define IG(...)
IG(abitrary * preprocessor, ++t 0kens)

Therefore, it is no longer necessary to entertain proposals about nested
comments.

BartC

unread,
Nov 12, 2011, 4:46:02 PM11/12/11
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnty695...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:
>> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message

>>> if (p < endp) /* don't run off the end! */
>>
>> (I still don't see what the problem would be with this example; what's
>> supposed to happen when that line in enclosed in another /*...*/
>> comment?)
>
> Currently, /*...*/ comments don't nest. As a result, once the
> compiler sees a /* sequence that's not inside another token (a string
> literal or, rarely, a character constant), it only needs to scan
> for a */ sequence, regardless of the context in which it appears.
>
> With nesting comments, after seeing an opening /*, there are several
> possible approaches:
>
> 1. Scan for /* and */ without tokenization and keep a count of the
> nesting level. This causes problems if a comment contains a string
> literal containing /* or */:
>
> /* const char open_comment[] = "/*"; */

Option (1) I think is the only viable one. And yes it does have a cost in
that spurious /* sequences are no longer allowed. But then /neither were
spurious */ sequences/!

What have people done in the past when */ was needed inside a /*...*/
comment? Whatever they did, perhaps they can do the same for /*!

> 2. Tokenize everything inside /*...*/ comments, so that the compiler
...
> 3. Define a new set of tokenization rules for use inside comments,
> so that comment delimiters within string literals within comments
> are ignored, but arbitrary text that doesn't necesssarily form a
> valid token sequence is accepted.

Those won't work because comments should be allowed to be anything at all;
you shouldn't have to write comments to conform to a syntax! So they might
be in badly written and punctuated language, or be badly written, incorrect
and incomplete source code, or metadata for all sorts of purposes.

The only restriction is that */ can't be included, and, for nested comments,
neither can /*.

> Note that '"' and '*/' are valid
> character constants.

'*/' is valid by itself, but not inside /*...*/ comment, where it will
generate a syntax error.

> And of course *any* of these changes would break existing code,
> which means the odd of any of them being adopted are close to zero.

Possibly. Checking code for /* sequences inside comments doesn't sound
difficult. But once nested comments are in use, they won't be backwards
incompatible.

--
bartc

Message has been deleted

Seebs

unread,
Nov 12, 2011, 4:40:22 PM11/12/11
to
On 2011-11-12, BartC <b...@freeuk.com> wrote:
> "Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
> news:j9m058$sil$1...@dont-email.me...
>> Would you like to be able to use a contraction like

>> if (p < endp) /* don't run off the end! */

> (I still don't see what the problem would be with this example; what's
> supposed to happen when that line in enclosed in another /*...*/ comment?)

Consider, if you will:

char *start_comment = "/*";

If comments don't nest, this is NEVER a problem. If comments nest, though,
this becomes a problem. The only way to get around that is to parse the
things inside a comment to see whether they really ought to be starting
a nested comment. But if we're parsing things inside comments:

/* don't run off the end! */

becomes a problem because it has a mismatched single quote.

Similarly, right now:

char *end_comment = "*/";

is fine, as long as you don't try to comment it out. Which is to say:

Comments should be text, not code, and comments are not the right tool
for cutting out bits of code. #if 0 is the right tool for cutting out bits
of code, because it works in terms of code. Comments used for code induce
serious problems.

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / usenet...@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.

BartC

unread,
Nov 12, 2011, 4:53:38 PM11/12/11
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:lnhb295...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:

>> That means you won't be able to have /* as part of comment text, whether
>> by
>> itself or part of a literal; is that really that big a deal?
>
> It would break existing code.
>
> If you're advocating a change to the C language, the fact that it
> would break existing code means such a change will not be adopted.
>
> If you're talking about a C-like language in which comments nest,
> then you're not talking about C.
>
> Which is it?

Sorry, I thought this part of the thread was about hard or how practical it
would be to make /*...*/ nestable.

Like the OP I also think this is desirable (and at one time thought they
*were* nestable, then found it didn't work!)

--
Bartc

BartC

unread,
Nov 12, 2011, 5:12:59 PM11/12/11
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201111121...@kylheku.com...
> On 2011-11-12, BartC <b...@freeuk.com> wrote:

>> In other words, anything is allowed, including source code, of C or
>> anything
>> else.
>
> No, because the formal language allowed within the comment excludes the
> digraph */ which may occur in the source code of C, inside a string
> literal, as part of a comment, or inside a // comment.

Well, yes; I mentioned */ a sentence or two later.

> It's more than a style issue; it's a formal language issue. Comments can
> only
> contain a subset of the possible set of C strings.
>
> It is useful that you can have a subset of C within comments, for
> instance,
> coding examples. They just can't have /*...*/ comments of their own, which
> is
> fine since they are already inside a comment which can explain everything.

What you're saying then is that /*...*/ comments are not a suitable
mechanism for commenting out code? The reason being that code might contain
(in perhaps one program in a thousand) a '*/' or "*/" token? Yet everyone
does this, and the world hasn't yet ended.

And perhaps /*...*/ isn't suitable for writing comments, period, since there
will from time to time be content that will break it. For example I couldn't
paste */this sentence/* into such a comment. Yet that doesn't bother many
people either.

> A mechanism for commenting out arbitrary code must be robust, period. This
> way
> it can be applied to a 50,000 line piece of source code without worry that
> anything breaks.
>
> #if 0 ... #endif satisfies that requirement.

Only if the code you're trying to 'comment out' is well-formed. If it's
unfinished, has open literals, and unbalanced #endifs scattered about, then
there will be problems. In this case /*...*/ might be a better bet...

--
bartc

Ian Collins

unread,
Nov 12, 2011, 5:22:36 PM11/12/11
to
On 11/13/11 11:12 AM, BartC wrote:
> "Kaz Kylheku"<k...@kylheku.com> wrote;
>
>> A mechanism for commenting out arbitrary code must be robust, period. This
>> way
>> it can be applied to a 50,000 line piece of source code without worry that
>> anything breaks.
>>
>> #if 0 ... #endif satisfies that requirement.
>
> Only if the code you're trying to 'comment out' is well-formed. If it's
> unfinished, has open literals, and unbalanced #endifs scattered about, then
> there will be problems. In this case /*...*/ might be a better bet...

That's a process problem, not a language one! Such "stuff" shouldn't
exist in code.

--
Ian Collins

Willem

unread,
Nov 12, 2011, 5:29:30 PM11/12/11
to
Keith Thompson wrote:
) Willem <wil...@toad.stack.nl> writes:
)> Which is why I have changed my preference to writing this:
)>
)> some_function(10 /* param1 */
)> ,20 /* param2 */
)> #if 0
)> ,30 /* param3 */
)> #endif
)> );
)>
)> And not only in C, but in almost any language.
)>
)> The point is that this plays a lot nicer with revision control systems,
)> because adding or removing an argument is a 1-line change, whereas in the
)> other case it can potentially change the previous line as well.
)
) And if you want to comment out the *first* argument?
)
) I see your point, but personally I find that layout rather hard on
) my eyes. The need to comment out a single parameter is rare enough
) that I don't think it's worth it.

And the need to play nice with revision control systems ?
I do it a lot more for the benefit of version control than anything else
(though commenting out is a very rudimentary form of version control.)

If the language did allow a trailing comma, it wouldn't be an issue,
and even a change on the first argument would not be a problem:

some_function(
10, /* param1 */
20, /* param2 */
30, /* param3 */
);

Not allowing trailing commas means you wither get in trouble for the first
argument, or the last argument. Oh, and it makes automatic code generation
a tiny bit harder as well (generating JSON has the same problem).

So I would be all in favour of this feature.
Is there any possible (existing) code that this would break ?
AFAIK, it will turn something that was a syntax error into good code.
(It may even be that existing implementations are allowed to let you off
with a warning and generate code as if the trailing comma weren't there.)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

Stephen Sprunk

unread,
Nov 12, 2011, 5:37:47 PM11/12/11
to
Amusing, but sort of misses the point since it hinges on _how_ "," is
defined rather than defending _why_ it is so defined.

Absent side effects, "x,y;" is equivalent to "y;". The expression ""
cannot have side effects, so ",y;" should also be equivalent to "y;" and
therefore be valid.

Absent side effects, ",y;" is equivalent to ";". The expression ""
cannot have side effects, so ",;" should also be equivalent to ";" and
therefore valid.

Absent side effects, "x,;" is equivalent to "x;". The expression ""
cannot have side effects, so "x,;" should also be equivalent to ";" and
therefore valid.

The problem is that both operands must be evaluated by the operator
before it can discard the results, and the current language definition
does not define how to evaluate a null expression. However, what if it did?

This is similar to not allowing objects of type void; such an object is
obviously meaningless, but there are certain corner cases where
uniformity matters more than meaning.

Jorgen Grahn

unread,
Nov 12, 2011, 5:55:47 PM11/12/11
to
On Fri, 2011-11-11, Aron Packer wrote:
> Hi all,
>
> (Apologies if this is in a FAQ somewhere, I couldn't find anything).
>
> Almost every time I do any significant amount of coding in C or C++, I
> end up wishing C-style comments would nest. It would make rapid
> debugging much more convenient (vs. #if 0/#endif or editor macros).

This is not an answer, but IMNSHO:

Commenting out code is almost always a mistake. Either
(a) read the code and reason about it until you can make it right
or
(b) remove it and pick it up from version control or the undo feature
of your editor if it turns out you really need it

At the other extreme, when people leave commented-out code in
committed code (code they feel is ready to share with others) you can
be reasonably sure that something is very wrong.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

unread,
Nov 12, 2011, 7:32:43 PM11/12/11
to
"BartC" <b...@freeuk.com> writes:
[...]
> What you're saying then is that /*...*/ comments are not a suitable
> mechanism for commenting out code? The reason being that code might contain
> (in perhaps one program in a thousand) a '*/' or "*/" token? Yet everyone
> does this, and the world hasn't yet ended.

/*...*/ comments are not a suitable mechanism for commenting out code
because code often includes its own /*...*/ comments, and they don't
nest.

Most of the issues involving '*/' or "*/" tokens don't even arise until
you start talking about changing the language to allow /*...*/ comments
to nest, and any such change would break existing code.

It's been mentioned several times that changing the language to allow
/*...*/ comments to nest would break existing code. If you've ever
acknowledged that very important point, I've missed it.

Keith Thompson

unread,
Nov 12, 2011, 7:36:57 PM11/12/11
to
Revision control systems can fend for themselves. If they end up
storing an extra line or two of diffs, that's not much of a problem.
Diff tools can be configured to show a few lines of context around each
change; some do so by default.

> If the language did allow a trailing comma, it wouldn't be an issue,
> and even a change on the first argument would not be a problem:
>
> some_function(
> 10, /* param1 */
> 20, /* param2 */
> 30, /* param3 */
> );
>
> Not allowing trailing commas means you wither get in trouble for the first
> argument, or the last argument. Oh, and it makes automatic code generation
> a tiny bit harder as well (generating JSON has the same problem).
>
> So I would be all in favour of this feature.
> Is there any possible (existing) code that this would break ?
> AFAIK, it will turn something that was a syntax error into good code.
> (It may even be that existing implementations are allowed to let you off
> with a warning and generate code as if the trailing comma weren't there.)

A syntax error, like a constraint violation, merely requires the
compiler to issue a diagnostic. What it does after that is undefined.

More realistically, perhaps, a compiler could permit trailing commas in
a non-conforming mode (most compilers are non-conforming by default
anyway).

Willem

unread,
Nov 13, 2011, 5:30:52 AM11/13/11
to
Keith Thompson wrote:
) Willem <wil...@toad.stack.nl> writes:
)> And the need to play nice with revision control systems ?
)> I do it a lot more for the benefit of version control than anything else
)> (though commenting out is a very rudimentary form of version control.)
)
) Revision control systems can fend for themselves. If they end up
) storing an extra line or two of diffs, that's not much of a problem.
) Diff tools can be configured to show a few lines of context around each
) change; some do so by default.

It's the merging where the problems start. I know, I've seen it happen.
Enough times for me to change my preference to the comma at the start of
theline, which would have avoided those merge conflicts.

)> So I would be all in favour of this feature.
)> Is there any possible (existing) code that this would break ?
)> AFAIK, it will turn something that was a syntax error into good code.
)> (It may even be that existing implementations are allowed to let you off
)> with a warning and generate code as if the trailing comma weren't there.)
)
) A syntax error, like a constraint violation, merely requires the
) compiler to issue a diagnostic. What it does after that is undefined.

So yes, they are allowed to let you off with a warning?
AFAIK, an implementation can define what it does in the case of certain
undefined behaviour. So, here's to compiler writers: make it a warning!

) More realistically, perhaps, a compiler could permit trailing commas in
) a non-conforming mode (most compilers are non-conforming by default
) anyway).

If enough compilers permit it, it would go into the next standard.

James Kuyper

unread,
Nov 13, 2011, 6:31:09 AM11/13/11
to
On 11/13/2011 05:30 AM, Willem wrote:
> Keith Thompson wrote:
...
> ) A syntax error, like a constraint violation, merely requires the
> ) compiler to issue a diagnostic. What it does after that is undefined.
>
> So yes, they are allowed to let you off with a warning?
> AFAIK, an implementation can define what it does in the case of certain
> undefined behaviour.

You can drop the word "certain" there, It is always the case that if the
behavior is undefined, the C standard imposes no restrictions, leaving
an implementation free to provide its own definition.
--
James Kuyper

Willem

unread,
Nov 13, 2011, 11:57:35 AM11/13/11
to
James Kuyper wrote:
) On 11/13/2011 05:30 AM, Willem wrote:
)> Keith Thompson wrote:
) ...
)> ) A syntax error, like a constraint violation, merely requires the
)> ) compiler to issue a diagnostic. What it does after that is undefined.
)>
)> So yes, they are allowed to let you off with a warning?
)> AFAIK, an implementation can define what it does in the case of certain
)> undefined behaviour.
)
) You can drop the word "certain" there, It is always the case that if the
) behavior is undefined, the C standard imposes no restrictions, leaving
) an implementation free to provide its own definition.

Yes, but the implementation can choose that it only does that for some
behaviours, and not for others. I see how the wording is confusing.

Phil Carmody

unread,
Nov 13, 2011, 4:55:57 PM11/13/11
to
For values of 'difficult' almost indistinguishable from 'trivial'

$ git reset --hard HEAD

> Anyway suppose the commented lines are actually intended to be read?

"The" commented lines? Which commented lines? Your hypothetical is
purely in your own head currently. It's hard to suggest solutions to
problems unless they're unambiguously described. If there's no reason
to change the code you've been given, and it's valid code - then just
leave it alone. That's not, however, any justification for creating
new code that contains evidence of sloppy development practices.

Phil
--
Unix is simple. It just takes a genius to understand its simplicity
-- Dennis Ritchie (1941-2011), Unix Co-Creator

Kenneth Brody

unread,
Nov 15, 2011, 2:17:35 PM11/15/11
to
On 11/11/2011 2:21 PM, Aron Packer wrote:
> Hi all,
>
> (Apologies if this is in a FAQ somewhere, I couldn't find anything).
>
> Almost every time I do any significant amount of coding in C or C++, I
> end up wishing C-style comments would nest. It would make rapid
> debugging much more convenient (vs. #if 0/#endif or editor macros).
>
> Anyway, was this an explicit design decision, or some sort of historical
> artifact? (e.g. too expensive to parse at the time). What other sorts of
> reasons might exist against nesting comments?

Note that I used pre-C89 compilers, some of which did nest comments. This
made for "interesting" results upon coming across something like this:

/* Some comment about "/*.*" wildcards. */

Though it still poses an "interesting" problem as to what to do with string
literals containing star-slash within them. As string literals, they have
no special meaning. Enclose the code in a comment, and all of a sudden,
they end the comment:

/*
char *operands = "^*/+-";
*/

Of course, this does fall back to the same rationale as quoted elsethread:

>> The C89 Committee rejected this proposal on the grounds that comments should
>> be used for adding documentation to a program, and that preferable mechanisms
>> already exist for source code exclusion. For example, [#if 0]


--
Kenneth Brody

Kenneth Brody

unread,
Nov 15, 2011, 2:22:52 PM11/15/11
to
On 11/11/2011 4:54 PM, Keith Thompson wrote:
> James Kuyper<james...@verizon.net> writes:
[...]
>> My preference is
>>
>> some_func(10 /* param1 */, 20 /* param2 */
>> #if 0
>> , 30 /* param3 */
>> #endif
>> );
>>
>> But I can understand why some might consider that ugly.
>
> If a comma were permitted after the last parameter declaration, you
> could just write:
>
> some_function(10 /* param1 */,
> 20 /* param2 */,
> #if 0
> 30 /* param3 */,
> #endif
> );

In such cases, I often use:

some_function( 10 /* param1 */
,20 /* param2 */
#if 0
,30 /* param3 */
#endif
);

A little awkward, but "less ugly".


> C99 changed the syntax to permit a trailing comma in an enum
> declaration. It would have made sense to permit a trailling
> comma for *any* comma-separated list. (Probably not for the comma
> operator, though.)

I definitely use such things in enums:

enum {
foo,
bar,
#if USE_BAZ
baz,
#endif
#if USE_FOOBAR
foobar,
#endif
};


--
Kenneth Brody

Ian Collins

unread,
Nov 15, 2011, 2:41:40 PM11/15/11
to
I still don't understand you anyone would do this.

Why not just remove the unused parameter?

--
Ian Collins

James Kuyper

unread,
Nov 15, 2011, 2:48:43 PM11/15/11
to
On 11/15/2011 02:41 PM, Ian Collins wrote:
> On 11/16/11 08:22 AM, Kenneth Brody wrote:
>> On 11/11/2011 4:54 PM, Keith Thompson wrote:
...
>>> If a comma were permitted after the last parameter declaration, you
>>> could just write:
>>>
>>> some_function(10 /* param1 */,
>>> 20 /* param2 */,
>>> #if 0
>>> 30 /* param3 */,
>>> #endif
>>> );
>>
>> In such cases, I often use:
>>
>> some_function( 10 /* param1 */
>> ,20 /* param2 */
>> #if 0
>> ,30 /* param3 */
>> #endif
>> );
>>
>> A little awkward, but "less ugly".
>
> I still don't understand you anyone would do this.

To remind future maintainers that this function used to have an extra
feature, which might someday need to be reinstated. As a general rule,
it would be associated with commented-out code within the body of the
function that makes use of the parameter. Keeping this old code, rather
than relying solely on the revision-control system serves to prevent
people from forgetting about the feature.
I've done things like this during debugging, but not for delivered code.

Ian Collins

unread,
Nov 15, 2011, 3:03:42 PM11/15/11
to
On 11/16/11 08:48 AM, James Kuyper wrote:
> On 11/15/2011 02:41 PM, Ian Collins wrote:
>> On 11/16/11 08:22 AM, Kenneth Brody wrote:
>>> On 11/11/2011 4:54 PM, Keith Thompson wrote:
> ....
>>>> If a comma were permitted after the last parameter declaration, you
>>>> could just write:
>>>>
>>>> some_function(10 /* param1 */,
>>>> 20 /* param2 */,
>>>> #if 0
>>>> 30 /* param3 */,
>>>> #endif
>>>> );
>>>
>>> In such cases, I often use:
>>>
>>> some_function( 10 /* param1 */
>>> ,20 /* param2 */
>>> #if 0
>>> ,30 /* param3 */
>>> #endif
>>> );
>>>
>>> A little awkward, but "less ugly".
>>
>> I still don't understand you anyone would do this.
>
> To remind future maintainers that this function used to have an extra
> feature, which might someday need to be reinstated. As a general rule,
> it would be associated with commented-out code within the body of the
> function that makes use of the parameter. Keeping this old code, rather
> than relying solely on the revision-control system serves to prevent
> people from forgetting about the feature.

That path is fraught with danger. The commented out code will become
stale because no one would bother to maintain it (for how could it be
tested?). It is far better to leave the original, in context, on a
branch and keep the main line clean.

--
Ian Collins

BartC

unread,
Nov 15, 2011, 3:37:59 PM11/15/11
to
"Ian Collins" <ian-...@hotmail.com> wrote in message
news:9iftjk...@mid.individual.net...
Because commenting something out isn't the same as deleting it for good.

Have you never written experimental code?

Besides, as soon as you delete a nondescript piece of code, usually the
application will suddenly stop working. With the weaker commitment of a
commenting-out, you can reinstate the code very easily.

Or sometimes you want to replace one bit of code by a variation of it, but
you still need the original code visible to work from. If the new version is
not quite right, you again need the original to start again. Quite often
there will be something in a line that is causing a problem, and you
temporarily comment-out different bits to investigate it.

Anyway there are dozens of reasons why people want to have commented-out
code, I don't think anyone disputes that. (Except perhaps you with your
super-duper version control systems which can remember and recover any mod
you ever did; in which case why should you care what anyone else uses
comments for?)

I just happen to think that #if 0 is a ugly way of doing this (with a few
problems of it's own), while nested comments is an elegant way.

--
Bartc


Ian Collins

unread,
Nov 15, 2011, 4:06:40 PM11/15/11
to
On 11/16/11 09:37 AM, BartC wrote:
> "Ian Collins"<ian-...@hotmail.com> wrote in message
> news:9iftjk...@mid.individual.net...
>> On 11/16/11 08:22 AM, Kenneth Brody wrote:
>
>>> In such cases, I often use:
>>>
>>> some_function( 10 /* param1 */
>>> ,20 /* param2 */
>>> #if 0
>>> ,30 /* param3 */
>>> #endif
>>> );
>>>
>>> A little awkward, but "less ugly".
>>
>> I still don't understand you anyone would do this.
>>
>> Why not just remove the unused parameter?
>
> Because commenting something out isn't the same as deleting it for good.
>
> Have you never written experimental code?

Often, but it doesn't find its way into production code.

> Besides, as soon as you delete a nondescript piece of code, usually the
> application will suddenly stop working. With the weaker commitment of a
> commenting-out, you can reinstate the code very easily.

Or in my case, the tests will fail and I'll revert the change.

> Or sometimes you want to replace one bit of code by a variation of it, but
> you still need the original code visible to work from. If the new version is
> not quite right, you again need the original to start again. Quite often
> there will be something in a line that is causing a problem, and you
> temporarily comment-out different bits to investigate it.

If this happens during an editing session, use the editor's undo/redo
facility.

If I want to make a change while keeping the original, I either open the
parent version in another editor window, or more often, open a visual
diff which highlights the changes clearly.

> Anyway there are dozens of reasons why people want to have commented-out
> code, I don't think anyone disputes that. (Except perhaps you with your
> super-duper version control systems which can remember and recover any mod
> you ever did; in which case why should you care what anyone else uses
> comments for?)

Using version control isn't rocket science. Subversion, git and
mercurial give you all the tools you need. They also integrate well
into the popular open source IDEs.

See my reply to James Kuyper, keeping stale, commented out code around
is as bad, if not worse, than having out of date design documents.

--
Ian Collins

Keith Thompson

unread,
Nov 15, 2011, 5:31:31 PM11/15/11
to
"BartC" <b...@freeuk.com> writes:
[...]
> I just happen to think that #if 0 is a ugly way of doing this (with a few
> problems of it's own), while nested comments is an elegant way.

It doesn't matter how elegant nested comments might or might not be.
They simply don't exist in C. I have yet to see you acknowledge that.

Willem

unread,
Nov 15, 2011, 5:40:38 PM11/15/11
to
Ian Collins wrote:
) On 11/16/11 08:22 AM, Kenneth Brody wrote:
)> In such cases, I often use:
)>
)> some_function( 10 /* param1 */
)> ,20 /* param2 */
)> #if 0
)> ,30 /* param3 */
)> #endif
)> );
)>
)> A little awkward, but "less ugly".
)
) I still don't understand you anyone would do this.
)
) Why not just remove the unused parameter?

some_function( 10 /* param1 */
,20 /* param2 */
#ifdef EXTRA_PARAMS
,30 /* param3 */
#endif
);

Oh, and besides that, writing it like above makes it easier to avoid merge
conflicts in sources where parameters are often tacked on at the end.

BartC

unread,
Nov 15, 2011, 5:41:47 PM11/15/11
to


"Keith Thompson" <ks...@mib.org> wrote in message
news:lnk4711...@nuthaus.mib.org...
> "BartC" <b...@freeuk.com> writes:
> [...]
>> I just happen to think that #if 0 is a ugly way of doing this (with a few
>> problems of it's own), while nested comments is an elegant way.

OK, 'would be an' instead of 'is an'.

> It doesn't matter how elegant nested comments might or might not be.
> They simply don't exist in C. I have yet to see you acknowledge that.

Clearly they don't, for arbitrary levels of /*...*/ comments, otherwise this
thread wouldn't exist.

Although nested comments of sorts can be achieved to a limited extent with
some combination of /*...*/, // and #if 0.

--
Bartc

Ian Collins

unread,
Nov 15, 2011, 5:48:51 PM11/15/11
to
On 11/16/11 11:40 AM, Willem wrote:
> Ian Collins wrote:
> ) On 11/16/11 08:22 AM, Kenneth Brody wrote:
> )> In such cases, I often use:
> )>
> )> some_function( 10 /* param1 */
> )> ,20 /* param2 */
> )> #if 0
> )> ,30 /* param3 */
> )> #endif
> )> );
> )>
> )> A little awkward, but "less ugly".
> )
> ) I still don't understand you anyone would do this.
> )
> ) Why not just remove the unused parameter?
>
> some_function( 10 /* param1 */
> ,20 /* param2 */
> #ifdef EXTRA_PARAMS
> ,30 /* param3 */
> #endif
> );

In that case, why not

#ifdef EXTRA_PARAMS
some_function( 10, 20, 30 );
#else
some_function( 10, 20 );
#endif

rather than adopt a naff style for some calls?

> Oh, and besides that, writing it like above makes it easier to avoid merge
> conflicts in sources where parameters are often tacked on at the end.

So does my alternative.

--
Ian Collins

Kaz Kylheku

unread,
Nov 15, 2011, 6:06:44 PM11/15/11
to
On 2011-11-15, BartC <b...@freeuk.com> wrote:
> "Ian Collins" <ian-...@hotmail.com> wrote in message
> news:9iftjk...@mid.individual.net...
>> On 11/16/11 08:22 AM, Kenneth Brody wrote:
>
>>> In such cases, I often use:
>>>
>>> some_function( 10 /* param1 */
>>> ,20 /* param2 */
>>> #if 0
>>> ,30 /* param3 */
>>> #endif
>>> );
>>>
>>> A little awkward, but "less ugly".

[ ... ]

>> Why not just remove the unused parameter?
>
> I just happen to think that #if 0 is a ugly way of doing this (with a few
> problems of it's own), while nested comments is an elegant way.

I showed several times how a simple macro can do it this way within
one line:

#define IGN(...) /* C99 variadic */

some_function(10, 20, IGN(30, ) );

Nests and everything:

IGN( IGN ( ... ) IGN ( IGN ( ... ) ) )

A limitation is that the the stuff that is being commented out has to have
balanced parentheses. I could live with that.

Kaz Kylheku

unread,
Nov 15, 2011, 6:13:04 PM11/15/11
to
In a situation where multiple developers find themselves regularly pounding on
new parameters onto the same set of functions, you want the coding convention
to be such that it maximizes the likelihood of a merge conflict, so they stop
and carefully review their integration process. There may still be a semantic
conflict even if you avoid the textual one. A new parameter being added to a
function that you've locally modified (including its argument list) is probably
a big deal, which could invalidate whatever you're doing inside that function.

BartC

unread,
Nov 15, 2011, 6:58:46 PM11/15/11
to
"Kaz Kylheku" <k...@kylheku.com> wrote in message
news:201111151...@kylheku.com...
> On 2011-11-15, BartC <b...@freeuk.com> wrote:

>> I just happen to think that #if 0 is a ugly way of doing this (with a few
>> problems of it's own), while nested comments is an elegant way.
>
> I showed several times how a simple macro can do it this way within
> one line:
>
> #define IGN(...) /* C99 variadic */
>
> some_function(10, 20, IGN(30, ) );
>
> Nests and everything:
>
> IGN( IGN ( ... ) IGN ( IGN ( ... ) ) )

I didn't believe it, but it seems to work...

> A limitation is that the the stuff that is being commented out has to have
> balanced parentheses. I could live with that.

I called mine COM() (why IGN?), and it means comments can be written like
this:

COM(...)

instead of:

/*...*/

But, both have similar problems in that either ( and ), or /* and */, must
be balanced, so from that point of view, what would be the difference?

Of course, nested COM() (or whatever it might be called) exists now, and
nested /**/ doesn't. But the argument against nested /**/ *was* that stray
/* or */ sequences would trip it up, in the same way that extra ( or ) might
cause a problem in the macro.

--
Bartc

Kaz Kylheku

unread,
Nov 15, 2011, 8:58:51 PM11/15/11
to
On 2011-11-15, BartC <b...@freeuk.com> wrote:
> "Kaz Kylheku" <k...@kylheku.com> wrote in message
> news:201111151...@kylheku.com...
>> On 2011-11-15, BartC <b...@freeuk.com> wrote:
>
>>> I just happen to think that #if 0 is a ugly way of doing this (with a few
>>> problems of it's own), while nested comments is an elegant way.
>>
>> I showed several times how a simple macro can do it this way within
>> one line:
>>
>> #define IGN(...) /* C99 variadic */
>>
>> some_function(10, 20, IGN(30, ) );
>>
>> Nests and everything:
>>
>> IGN( IGN ( ... ) IGN ( IGN ( ... ) ) )
>
> I didn't believe it, but it seems to work...

Why didn't you believe it? I often test stuff before posting! :)

>> balanced parentheses. I could live with that.
>
> I called mine COM() (why IGN?), and it means comments can be written like
> this:

Because, sigh, it's not commenting! It's for ignoring program tokens.

IGN comes from the Common Lisp habit: #+IGN expr causes expr to be
ignored, assuming the symbol :IGN is not in the platform *features* list.
I've never seen Lisp's #+ or #- used for commenting; that is ridiculous.

(Lisp people: don't shoot me, I know this kludge is frowned upon by some,
and I don't use it myself, but rather #+(and) expr.)

> But, both have similar problems in that either ( and ), or /* and */, must
> be balanced, so from that point of view, what would be the difference?
> Of course, nested COM() (or whatever it might be called) exists now, and
> nested /**/ doesn't. But the argument against nested /**/ *was* that stray
> /* or */ sequences would trip it up, in the same way that extra ( or ) might
> cause a problem in the macro.

The differences is that the stuff inside IGN(...) is preprocessor tokens, not
an arbitrary comment. It syntactically has to be a valid macro call! So it is
not messed up by the following:

IGN( char lparen = '('; )

On the other and it is messed up by this:

if (!x)
foo(); IGN(Don't foo if x is true!)

Do you still want to call it COM?

Kenneth Brody

unread,
Nov 16, 2011, 12:57:45 PM11/16/11
to
On 11/15/2011 2:41 PM, Ian Collins wrote:
> On 11/16/11 08:22 AM, Kenneth Brody wrote:
[...]
>> In such cases, I often use:
>>
>> some_function( 10 /* param1 */
>> ,20 /* param2 */
>> #if 0
>> ,30 /* param3 */
>> #endif
>> );
>>
>> A little awkward, but "less ugly".
>
> I still don't understand you anyone would do this.
>
> Why not just remove the unused parameter?

Would this make you feel better?

some_function( 10 /* param1 */
,20 /* param2 */
#if INCLUDE_DEBUG_INFO
,__FILE__
,__LINE__
#endif
);


--
Kenneth Brody

Ian Collins

unread,
Nov 16, 2011, 1:42:38 PM11/16/11
to
As I said yesterday, you don't have to resort to such an awful layout to
accommodate conditional compilation:

#if INCLUDE_DEBUG_INFO
some_function( 10, 20, __FILE__, __LINE__ );
#else
some_function( 10, 20 );
#endif

--
Ian Collins

John Gordon

unread,
Nov 16, 2011, 1:57:09 PM11/16/11
to
In <9iiegu...@mid.individual.net> Ian Collins <ian-...@hotmail.com> writes:

> As I said yesterday, you don't have to resort to such an awful layout to
> accommodate conditional compilation:

> #if INCLUDE_DEBUG_INFO
> some_function( 10, 20, __FILE__, __LINE__ );
> #else
> some_function( 10, 20 );
> #endif

This violates the DRY principle. What happens when you (or a future
maintainer) change the value of an argument in the first call but neglect
to change it in the second call?

--
John Gordon A is for Amy, who fell down the stairs
gor...@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

Ian Collins

unread,
Nov 16, 2011, 2:48:06 PM11/16/11
to
On 11/17/11 07:57 AM, John Gordon wrote:
> In<9iiegu...@mid.individual.net> Ian Collins<ian-...@hotmail.com> writes:
>
>> As I said yesterday, you don't have to resort to such an awful layout to
>> accommodate conditional compilation:
>
>> #if INCLUDE_DEBUG_INFO
>> some_function( 10, 20, __FILE__, __LINE__ );
>> #else
>> some_function( 10, 20 );
>> #endif
>
> This violates the DRY principle. What happens when you (or a future
> maintainer) change the value of an argument in the first call but neglect
> to change it in the second call?

The relevant tests will fail and the code will be fixed.

--
Ian Collins

Keith Thompson

unread,
Nov 16, 2011, 2:50:23 PM11/16/11
to
Even with perfect test coverage, you've just spent time fixing a bug
(and tracking down the cause) that wouldn't ever have occurred if
you'd written "10, 20" only once.

Ian Collins

unread,
Nov 16, 2011, 3:00:14 PM11/16/11
to
On 11/17/11 08:50 AM, Keith Thompson wrote:
> Ian Collins<ian-...@hotmail.com> writes:
>> On 11/17/11 07:57 AM, John Gordon wrote:
>>> In<9iiegu...@mid.individual.net> Ian Collins<ian-...@hotmail.com> writes:
>>>
>>>> As I said yesterday, you don't have to resort to such an awful layout to
>>>> accommodate conditional compilation:
>>>
>>>> #if INCLUDE_DEBUG_INFO
>>>> some_function( 10, 20, __FILE__, __LINE__ );
>>>> #else
>>>> some_function( 10, 20 );
>>>> #endif
>>>
>>> This violates the DRY principle. What happens when you (or a future
>>> maintainer) change the value of an argument in the first call but neglect
>>> to change it in the second call?
>>
>> The relevant tests will fail and the code will be fixed.
>
> Even with perfect test coverage, you've just spent time fixing a bug
> (and tracking down the cause) that wouldn't ever have occurred if
> you'd written "10, 20" only once.

The original example was fairly trivial; imagine the case where the
parameter order changed, or there are more than two possibilities.

I have an application that works with several version of an unofficial
system library. To date there have been 4 changes to the parameters for
one function....

--
Ian Collins

Ben Pfaff

unread,
Nov 16, 2011, 2:57:36 PM11/16/11
to
Ian Collins <ian-...@hotmail.com> writes:

> As I said yesterday, you don't have to resort to such an awful layout
> to accommodate conditional compilation:
>
> #if INCLUDE_DEBUG_INFO
> some_function( 10, 20, __FILE__, __LINE__ );
> #else
> some_function( 10, 20 );
> #endif

#ifdef INCLUDE_DEBUG_INFO
#define somefunction(a, b) somefunction(a, b, __FILE__, __LINE__)
#endif
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

Kaz Kylheku

unread,
Nov 16, 2011, 3:20:56 PM11/16/11
to
On 2011-11-16, Keith Thompson <ks...@mib.org> wrote:
> Ian Collins <ian-...@hotmail.com> writes:
>> On 11/17/11 07:57 AM, John Gordon wrote:
>>> In<9iiegu...@mid.individual.net> Ian Collins<ian-...@hotmail.com> writes:
>>>
>>>> As I said yesterday, you don't have to resort to such an awful layout to
>>>> accommodate conditional compilation:
>>>
>>>> #if INCLUDE_DEBUG_INFO
>>>> some_function( 10, 20, __FILE__, __LINE__ );
>>>> #else
>>>> some_function( 10, 20 );
>>>> #endif
>>>
>>> This violates the DRY principle. What happens when you (or a future
>>> maintainer) change the value of an argument in the first call but neglect
>>> to change it in the second call?
>>
>> The relevant tests will fail and the code will be fixed.
>
> Even with perfect test coverage, you've just spent time fixing a bug
> (and tracking down the cause) that wouldn't ever have occurred if
> you'd written "10, 20" only once.

Also this bug will occur either in the build with debug info or the one
without.

The perfect test coverage has to be repeated for both builds of the program.

Ian Collins

unread,
Nov 16, 2011, 3:47:13 PM11/16/11
to
On 11/17/11 08:57 AM, Ben Pfaff wrote:
> Ian Collins<ian-...@hotmail.com> writes:
>
>> As I said yesterday, you don't have to resort to such an awful layout
>> to accommodate conditional compilation:
>>
>> #if INCLUDE_DEBUG_INFO
>> some_function( 10, 20, __FILE__, __LINE__ );
>> #else
>> some_function( 10, 20 );
>> #endif
>
> #ifdef INCLUDE_DEBUG_INFO
> #define somefunction(a, b) somefunction(a, b, __FILE__, __LINE__)
> #endif

Yes, there are many ways to skin that particular cat!

My objection to the earlier proposals was more than just the awful
style: it falls apart for all but the most trivial examples.

--
Ian Collins

Noob

unread,
Nov 17, 2011, 5:21:50 AM11/17/11
to
James Kuyper wrote:

>> Another way of accomplishing these goals is with an if statement:
>> if (0) {
>> /* code to be excluded */
>> }
>>
>> Many modern compilers will generate no code for this if statement.

However, some will generate a warning ;-)

Phil Carmody

unread,
Nov 18, 2011, 8:49:35 AM11/18/11
to
A few years while I was complifying some code, I added some
extra parameters to many functions that I found I wasn't really
using. The way I did it was something like the following (grab
a bucket...)

#if HAVE_EXTRA_CRAP
# define EXTRA_PARAMS(p1,p2) , float p1, float p2
# define EXTRA_ARGS(p1,p2) , p1, p2
#else
# define EXTRA_PARAMS(p1,p2) /* no extra parameters */
# define EXTRA_ARGS(p1,p2) /* no extra arguments */
#endif

int some_caller(int foo EXTRA_PARAMS(mini, maxi))
{
return some_function(foo-1 EXTRA_ARGS(mini, maxi))
}

I do wish the 'trailing comma' had wider acceptance, as it
would make the above less barfworthy.

Fortunately, there's a happy ending. I saw the error of my
ways, and just removed all the extra stuff I no longer wanted
to use, and I have to dig into the version control system if
I ever want to see it again.

Phil
--
Unix is simple. It just takes a genius to understand its simplicity
-- Dennis Ritchie (1941-2011), Unix Co-Creator

Phil Carmody

unread,
Nov 18, 2011, 8:55:10 AM11/18/11
to
I support both behaviours. Such code is smell, and getting rid of smells
should be encouraged.

James Kuyper

unread,
Nov 18, 2011, 10:15:44 AM11/18/11
to
On 11/18/2011 08:49 AM, Phil Carmody wrote:
...
> A few years while I was complifying some code, I added some

You don't always have to coin a new word. Try "complicating".

Phil Carmody

unread,
Nov 18, 2011, 10:57:01 AM11/18/11
to
You don't understand - the use of the extra parameters was to *simplify* things!
0 new messages