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

Interesting question in C

4 views
Skip to first unread message

Alex Lemelev

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
What is the output of the following C program ?

void main()
{
int i , j = 3;

i = ++j * ++j;
printf("%d\n", i);
}

P.S. dont compile it !!!

Ben Pfaff

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
"Alex Lemelev" <Alex.L...@ecitele.com> writes:

What is the output of the following C program ?

void main()

Undefined behavior.

{
int i , j = 3;

i = ++j * ++j;

Undefined behavior.

printf("%d\n", i);
}

Idiot.
--
(In need of a experienced ANSI C and cross-platform programmer?
I'm seeking a programming internship for summer of 1999.)
Please: do not email me copies of your posts to comp.lang.c
do not ask me C questions via email; post them instead

Mathew Hendry

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
"Alex Lemelev" <Alex.L...@ecitele.com> wrote:

: What is the output of the following C program ?

There needn't be any. It invokes undefined behaviour in two places.

: void main()

Here. The behaviour of main is defined only if it returns an int.

: {
: int i , j = 3;


:
: i = ++j * ++j;

And here. j is modified twice with no intervening sequence point.

: printf("%d\n", i);
: }

-- Mat.


Mathew Hendry

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
ma...@vissci.com (Mathew Hendry) wrote:

: "Alex Lemelev" <Alex.L...@ecitele.com> wrote:
:
: : What is the output of the following C program ?
:
: There needn't be any. It invokes undefined behaviour in two places.

Three, even.

: : void main()


:
: Here. The behaviour of main is defined only if it returns an int.
:
: : {
: : int i , j = 3;
: :
: : i = ++j * ++j;
:
: And here. j is modified twice with no intervening sequence point.
:
: : printf("%d\n", i);

And here. No prototype for printf was provided.

: : }

P.S. Read the FAQ.

-- Mat.


J. Benz

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to

Alex Lemelev wrote:

> What is the output of the following C program ?
>

> void main()
> {


> int i , j = 3;
>
> i = ++j * ++j;

> printf("%d\n", i);
> }
>

> P.S. dont compile it !!!

Use a handkerchief, willya... Those demons just got all over the
keyboard.


Edward_Hill

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
Alex Lemelev wrote:
>
> What is the output of the following C program ?
>
> void main()
> {
> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
> }
>
> P.S. dont compile it !!!

Well I think my ANSI compiler will choke on the void main
before it even gets down to the ++ bits.

But well ++ has higher precedence than *
so I'd imagine j is incremented to 4 and then
incremented to 5 and then multiplied by itself to
give 25.
So what's the answer?

Ed


Jack Klein

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
On Thu, 05 Nov 1998 14:22:10 +0000, Edward_Hill <Edwar...@gec.nospam.com>
wrote:

<Jack>

Imagine anything you want. That line produces undefined behavior because it
modifies the value of j twice without an intervening sequence point. Since
the behavior is undefined, nothing that happens is wrong. Of course nothing
that happens is right, either.

</Jack>


Sunil Rao

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
Edward_Hill wrote:
>
> Alex Lemelev wrote:
> >
> > What is the output of the following C program ?
> >
> > void main()
> > {
> > int i , j = 3;
> >
> > i = ++j * ++j;
> > printf("%d\n", i);
> > }
> >
> > P.S. dont compile it !!!
>
> Well I think my ANSI compiler will choke on the void main
> before it even gets down to the ++ bits.
>
> But well ++ has higher precedence than *
> so I'd imagine j is incremented to 4 and then
> incremented to 5 and then multiplied by itself to
> give 25.

erm... no. The behaviour is pretty much undefined.

> So what's the answer?

See the FAQ - http://www.eskimo.com/~scs/C-Faq/top.html :)

--
{ Sunil Rao }
"And India acquired yet another willing convert to the philosophy of
the meaningfully meaningless... Or was it the meaninglessly
meaningful? Did anyone know what was happening?" -- Gita Mehta

Alex...@scitex.com

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,

"Alex Lemelev" <Alex.L...@ecitele.com> wrote:
>
> void main()
> {
> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
> }
> What is the output of the program ?

Demons flying out of your nose and formatting your
hard disk.
For a more detailed explanation please read the FAQ at
http://www.eskimo.com/~scs/C-faq/top.html

--
Regards,
Alex Krol
Disclaimer: I'm not speaking for Scitex Corporation Ltd

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Steve Summit

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to Alex.L...@ecitele.com
[posted and mailed]

In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
Alex.L...@ecitele.com writes:
> What is the output of the following C program ?


> void main()
> {
> int i , j = 3;
> i = ++j * ++j;
> printf("%d\n", i);
> }

> P.S. dont compile it !!!

Okay, without compiling it, I predict that the program will
print "forty-two". Am I right?

Steve Summit

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
In article <3641B4...@gec.nospam.com>, Edward Hill writes:

>Alex Lemelev wrote:
>> int i , j = 3;
>> i = ++j * ++j;
>
> But well ++ has higher precedence than *
> so I'd imagine j is incremented to 4 and then incremented
> to 5 and then multiplied by itself to give 25.
> So what's the answer?

The answer, of course, is that there is no answer.

Attempting to use precedence rules to analyze malformed
expressions like these is a popular pastime, but it turns out
not to help. It's true that the "outputs" of the two ++'s are
to be multiplied together, but what are those outputs?

Consider a related expression:

i = f1() * f2();

Function calls have higher precedence than multiplication, so
the two functions will be called before the multiplication can
happen. But which function is called first, f1 or f2? No one
can say, and different compilers do it differently.

(I suppose you might try to invoke the left-to-right associativity
of multiplication to claim that f1 would be called first, but
associativity doesn't help here, either. Associativity says that
in f1() * f2() * f3(), the results of f1 and f2 are multiplied
together before being multiplied by the result of f3, but we
still don't know which order the functions were called in.
f3 might be called first, and its result saved for last.)

The situation with ++j * ++j is actually even worse than with
f1() * f2(). In the function call case, it's probably true that
either f1 is called first and then f2, or f2 is called first
and then f1. Applying the same logic to ++j * ++j, we might
imagine that either the left-hand ++j gets evaluated first and
then the right-hand one, yielding 4 * 5 = 20, or else the
right-hand one gets evaluated first and then the left-hand one,
yielding 5 * 4 = 20. But it turns out that this analysis doesn't
work, either.

The problem is that ++j does two things. It delivers the value
j+1 to the surrounding expression, and it stores the value j+1
back into j, thus incrementing it. But we don't know (because
the C Standard doesn't tell us) precisely when the updated value
of j gets written back to j.

In some expressions, it doesn't matter. If we wrote

i = ++j * k;

the compiler could emit code which essentially either
interpreted the expression as

j = j + 1;
i = j * k;

or

i = (j+1) * k;
j = j + 1;

If we wrote

i = ++j * ++k;

there would be at least six possible interpretations:

j = j + 1; k = k + 1;
k = k + 1; j = j + 1;
i = j * k; i = j * k;

i = (j+1) * (k+1); i = (j+1) * (k+1);
j = j + 1; k = k + 1;
k = k + 1; j = j + 1;

j = j + 1; k = k + 1;
i = j * (k+1); i = (j+1) * k;
k = k + 1; j = j + 1;

Now, all six of those interpretations yield the same answer
(16, if j and k both start out as 3). But if you replace k in
each of them by j, resulting in six possible interpretations of
the expression ++j * ++j, you can get at least three different
answers (16, 20, and 25, by my reckoning).

But it gets worse. The official wording in the ANSI/ISO C
Standard says that if you attempt to modify the same object at
one spot within an expression and refer to that same object at
another spot (as in the expression ++j * j), or if you attempt
to modify the same object twice within an expression (as in
the expression ++j * ++j), the results are undefined [footnote 1].
What this means is that the compiler isn't even required to
choose among the two (or six, or however many you can come up
with) "plausible" interpretations of the expression; it can do
any random thing it wants to, and it won't be in violation of the
Standard. (In practice, it's not so much that compilers do "any
random thing they want to" in these situations, but what does
happen is that they do any random thing that falls out of their
algorithms for handling well-formed expressions, algorithms which
are not designed -- because they do not have to be -- to do
anything reasonable with undefined expressions.)

Now, you might say (and I'd agree with you) that the expression
i = ++j * ++j would be so unlikely to come up in a real program
that it hardly matters what it does. But if you think you can
analyze that expression and figure out what it does, then there's
a flaw either in your analysis or in your understanding of C.
And I would urge you to repair that flaw -- to teach yourself
that you *cannot* analyze the behavior of expressions like these
-- because that way you won't falsely imagine that you can
predict the behavior of other, more insidious undefined
expressions which *do* occasionally crop up in real programs,
expressions which will cause real problems if they are retained,
expressions which it will do nobody any positive good to be able
to analyze or justify, expressions which should ideally be
recognized as the undefined expressions they are and banished
from the program as soon as possible.

As an example of how a "more insidious undefined expression" can
in fact crop up in a real program, consider the following
decidedly non-hypothetical scenario. (The reason I know it's
not hypothetical is that I know the programmer it happened to.)
The program is the interpreter for a stack machine, and it
contains code like

switch(op)
{
case ADD:
push(pop() + pop());
break;
case SUBTRACT:
tmp = pop();
push(pop() - tmp);
break;
case MULTIPLY:
push(pop() * pop());
break;
case SUBTRACT:
tmp = pop();
if(tmp == 0) {error("divide by 0"); break; }
push(pop() / tmp);
break;
...

In the original implementation, push() and pop() are function
calls. The original programmer, knowing that the order of
function calls within an expression is unpredictable (see our
discussion of f1 and f2 above) has taken care to use a temporary
variable to ensure that the operands are popped in the right
order for subtraction and division, where it matters.

But the interpreter is too slow, and a later programmer reasons
that part of the problem is function call overhead. (Most of the
time, it's a good idea not to worry about function call overhead
too much, but in some situations, such as the inner loop of an
interpreter which might be interpreting huge amounts of code, it
can indeed be significant.)

I don't remember if the push and pop functions were

void push(val)
{
stack[stackp++] = val;
}

pop()
{
return stack[--stackp];
}

or

void push(val)
{
*stackp++ = val;
}

pop()
{
return *--stackp;
}

(That is, although the stack and the stack pointer were both
global, I don't remember whether the stack pointer was an index
or a pointer into the stack.) But, in either case, it's easy to
see how we might replace the push and pop functions with macros,
thus removing the function call overhead in the critical inner
loop, without rewriting the entire interpreter. (In fact, this
interpreter had hundreds of operators, some much more complicated
than simple arithmetic, so there were hundreds of calls to push()
and pop() spread across many source files.)

The macros would, of course, either be

#define push(val) (stack[stackp++] = (val))
#define pop() stack[--stackp]

or

#define push(val) (*stackp++ = (val))
#define pop() *--stackp

and this seems like a very simple way to dramatically increase
the efficiency of the interpreter. (It did, too, by 20 or 30
percent.) The problem was that the interpreter also began
delivering wildly erroneous answers.

The problem turned out to be in those innocuous-looking lines

push(pop() + pop());
and
push(pop() * pop());

for addition and multiplication. When push() and pop() are
macros, these lines expand to either

(stack[stackp++] = (stack[--stackp] + stack[--stackp]));
(stack[stackp++] = (stack[--stackp] * stack[--stackp]));
or

(*stackp++ = (*--stackp + *--stackp));
(*stackp++ = (*--stackp * *--stackp));

And these expressions bear an eerie similarity to the one that
began this thread. (They're complicated by an added level of
indirection, and they each attempt to modify stackp *three* times
within one expression.) And yes, under a popular, real-world
compiler, namely gcc, these expressions did produce some crazy
result which was not at all the expected one but which, by a
strict and proper interpretation of the C Standard, was *not*
incorrect. (That is, it was not incorrect for the compiler and
the emitted code to have produced the undesired result.) The
compiler had not done anything wrong; the error was on the part
of the programmer who attempted to replace the function calls
with macros, macros which proved to be dangerous because of
their embedded side effects.

And finally, in case anyone is doubting the truth of this story,
I can tell you that the maintenance programmer who introduced the
undefined behavior was (as others of you have probably already
guessed) none other than the maintainer of the comp.lang.c FAQ
list, Steve Summit, who presumably ought to have known better.

Steve Summit
s...@eskimo.com


Footnote 1: The real rule on undefined expressions is that you
can't modify an object twice, or modify and then inspect it,
between sequence points. There are a few operators -- including
function calls -- which do introduce sequence points, so it's
possible to come up with expressions which contain multiple side
effects but which are not undefined.

Martin Ambuhl

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
Alex Lemelev wrote:
>
> What is the output of the following C program ?
>
> void main()
> {
> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
> }
>
> P.S. dont compile it !!!

This last line is unnecessary, since this obviously illegal and
illiterate code should not compile.

--
Martin Ambuhl (mam...@earthlink.net)
Note: mam...@tiac.net will soon be inactive


tst...@my-dejanews.com

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,

"Alex Lemelev" <Alex.L...@ecitele.com> wrote:
> What is the output of the following C program ?
>
> void main()
> {
> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
> }
>
> P.S. dont compile it !!!
>

What's interesting about it ? It's all well-documented undefined behaviour.
Interesting is something like Duff's device or 1["abc"] , this i just boring.

--
Tristan Styles

Failure is not an option
It is Standard Operating Procedure

Will Rose

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
Alex Lemelev (Alex.L...@ecitele.com) wrote:
: What is the output of the following C program ?

: void main()
: {
: int i , j = 3;
:
: i = ++j * ++j;
: printf("%d\n", i);
: }

: P.S. dont compile it !!!

Well, since you've omitted <stdio.h> there doesn't seem much point
in looking further, but you've also, of course, added a couple of
lines of undefined behaviour and omitted a return statement at the
end of main(). However, the line 'int i, j = 3' seems correct:
what did you intend to write?


Will
c...@crash.cts.com


Mike McCarty

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
If you went over to a newsgroup like soc.british and posted something
like

What does this sentence mean?

This sentence no verb!

P.S. don't read it!

What kind of response do you think you would get?

This is not on-topic and clutters this newsgroup, which is already so
glutted with trash as to be virtually useless.

Mike

In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
Alex Lemelev <Alex.L...@ecitele.com> wrote:

)What is the output of the following C program ?
)
)void main()
){
) int i , j = 3;
)
) i = ++j * ++j;
) printf("%d\n", i);
)}
)
)P.S. dont compile it !!!


--
----
char *p="char *p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}
This message made from 100% recycled bits.
I don't speak for Alcatel <- They make me say that.

John...@my-dejanews.com

unread,
Nov 5, 1998, 3:00:00 AM11/5/98
to
In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
"Alex Lemelev" <Alex.L...@ecitele.com> wrote:
> What is the output of the following C program ?
>
> void main()
> {

> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
> }
>

A recruitment poster for Microsoft?

Sorry, sorry, it's been a bad week...

> P.S. dont compile it !!!
>

Sage advice.

Jos A. Horsmeier

unread,
Nov 6, 1998, 3:00:00 AM11/6/98
to
Steve Summit wrote:
> In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
> Alex.L...@ecitele.com writes:

> > What is the output of the following C program ?
> > void main()
> > {
> > int i , j = 3;
> > i = ++j * ++j;
> > printf("%d\n", i);
> > }

> > P.S. dont compile it !!!

> Okay, without compiling it, I predict that the program will
> print "forty-two". Am I right?

Don't be silly Steve, everybody knows that this littly
thingy would turn the computer into a ballet dancer,
all painted purple, dancing on top of the piano, singing
'undefined behavior! undefined behavior!'

kind regards,

Jos aka j...@and.nl

ps. ;-)

Dan Pop

unread,
Nov 6, 1998, 3:00:00 AM11/6/98
to
In <3641B4...@gec.nospam.com> Edward_Hill <Edwar...@gec.nospam.com> writes:

>Alex Lemelev wrote:
>>
>> What is the output of the following C program ?
>>
>> void main()
>> {
>> int i , j = 3;
>>
>> i = ++j * ++j;
>> printf("%d\n", i);
>> }
>>
>> P.S. dont compile it !!!

I did. With two compilers. Here are the results:

ues5:~/tmp 146> cc test.c
ues5:~/tmp 147> ./a.out
25
ues5:~/tmp 148> gcc test.c
ues5:~/tmp 149> ./a.out
20

None of the compilers is broken. Your code is.

>Well I think my ANSI compiler will choke on the void main
>before it even gets down to the ++ bits.
>

>But well ++ has higher precedence than *
>so I'd imagine j is incremented to 4 and then
>incremented to 5 and then multiplied by itself to
>give 25.
>So what's the answer?

The answer is: READ THE FAQ!!!

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

Rahul Agarwal

unread,
Nov 6, 1998, 3:00:00 AM11/6/98
to
Sorry guys , but i could not help compiling it. It compiles fine on AIX
and the output is 20.


>


Cristian Vlasceanu

unread,
Nov 6, 1998, 3:00:00 AM11/6/98
to

Steve Summit <s...@eskimo.com> wrote in article
<71sgtn$mid$1...@eskinews.eskimo.com>...
> [posted and mailed]


>
> In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
> Alex.L...@ecitele.com writes:

> > What is the output of the following C program ?
> > void main()
> > {
> > int i , j = 3;
> > i = ++j * ++j;
> > printf("%d\n", i);
> > }
> > P.S. dont compile it !!!
>

> Okay, without compiling it, I predict that the program will
> print "forty-two". Am I right?

Actually it depends on the localization. On some machines it will print
"quarante-deux" :)


rob

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to

Steve Summit wrote in message
>

>> What is the output of the following C program ?
>> void main() {
>> int i , j = 3;
>> i = ++j * ++j;
>> printf("%d\n", i); }
>> P.S. dont compile it !!!
>
> Okay, without compiling it, I predict that the program will
> print "forty-two". Am I right?

This hardly qualifies as the question of life, existence the
universe and everything

rob


User923005

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
Bobboli:
Of course, that is also a possible output for the above, if you fail to follow
the valuable P.S. warning message.
It might also print out all possible digits for pi (if you can wait long
enough) or draw a portrait of your mother composing a poem in the honor of a
weird holy man, holding a rubber duck.
But who has the duck, the holy man or your mother?

--
C-FAQ ftp sites: ftp://ftp.eskimo.com ftp://rtfm.mit.edu
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ Book: ISBN 0-201-84519-9.
Want Software? Algorithms? Pubs? http://www.infoseek.com

Neil Trotter

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
In article <36432DDC...@ccd.harris.com>, Rahul Agarwal said:

> Sorry guys , but i could not help compiling it. It compiles fine on AIX
> and the output is 20.
>

Compiles fine with GCC under Linux too, and the output is 25. This is
what is meant by "undefined behaviour".


-- Neil.


Neil Trotter, Canewdon, UK
ne...@nook.demon.co.uk
http://www.nook.demon.co.uk/

Helmut Leitner

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
rob wrote:
>
> Steve Summit wrote in message
> >
>
> >> What is the output of the following C program ?
> >> void main() {
> >> int i , j = 3;
> >> i = ++j * ++j;
> >> printf("%d\n", i); }
> >> P.S. dont compile it !!!
> >
> > Okay, without compiling it, I predict that the program will
> > print "forty-two". Am I right?

"zweiundvierzig" on my computer.

> This hardly qualifies as the question of life, existence the
> universe and everything

IMHO the really interesting questions are:

1. Why was this problem (as part of the subproblem to make C
easier to learn and use) never attacked?

2. Why was the only natural solution:

i = ++j * ++j;

shall have the same result as

++j; ++j;
i=j*j;

(in a general form) never made part of the standard?

So that the old veterans can tease the newbees
and have fun for the next 1000 years? :-)

Helmut

Mathew Hendry

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
Helmut Leitner <lei...@hls.via.at> wrote:

>IMHO the really interesting questions are:
>
>1. Why was this problem (as part of the subproblem to make C
> easier to learn and use) never attacked?

Of course the problem was attacked, and tradeoffs were made. Nasty,
hard to understand expressions such as "i = ++j + ++j" were made
illegal in order to allow nice, easy to understand expressions to be
implemented more efficiently.

>2. Why was the only natural solution:
>
> i = ++j * ++j;
>
> shall have the same result as
>
> ++j; ++j;
> i=j*j;
>
> (in a general form) never made part of the standard?

Explain why this is the "natural" solution. My reading puts it closer
to,

i = (j + 1) + (j + 2);
j += 2;

which is what the programmer should have written in the first place,
precisely to avoid such ambiguities.

-- Mat.


Cameron Foster

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
On 7 Nov 1998 06:04:20 GMT, user9...@aol.com (User923005) wrote:
>.....

>enough) or draw a portrait of your mother composing a poem in the honor of a
>weird holy man, holding a rubber duck.
>But who has the duck, the holy man or your mother?

Depends on the color of the duck.

--

Cameron Foster
cdfo...@ix.netcom.com
http://www2.netcom.com/~cdfoster/

Steve Summit

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
In article <3644A64E...@hls.via.at>, Helmut Leitner

<lei...@hls.via.at> writes:
> 1. Why was this problem (as part of the subproblem to make C
> easier to learn and use) never attacked?

Well, to be brutally frank and honest: The subproblem of making
C easier to learn or use has never been attacked, nor (as far as
I know) have either of these ever been goals of C.

> 2. Why was the only natural solution:
> i = ++j * ++j;
> shall have the same result as
> ++j; ++j;
> i=j*j;
> (in a general form) never made part of the standard?

I'm quite willing to address that question, but first we have to
answer a sub-question (which Mathew Hendry has already reminded
us of):

What is the natural interpretation of i = ++j * ++j?
Is it

++j; ++j;
i=j*j;
or
i = ++j;
i *= ++j;

or perhaps

i = ++j;
i *= j;
++j;

I'm not claiming that the third interpretation is natural,
but there are plenty of arguments in favor of the second one
(especially if you're looking to express your rule for
interpreting these in general form).

Steve Summit
s...@eskimo.com

Lawrence Kirby

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
In article <36495681....@news.demon.co.uk>
ne...@nook.demon.co.uk "Neil Trotter" writes:

>In article <36432DDC...@ccd.harris.com>, Rahul Agarwal said:
>
>> Sorry guys , but i could not help compiling it. It compiles fine on AIX
>> and the output is 20.
>>
>
>Compiles fine with GCC under Linux too, and the output is 25. This is
>what is meant by "undefined behaviour".

Indeed some compilers will even produce different results depending on
the level of optimisation set.

This reminds me of positively the most incompetent C tutorial author I've
ever seen: Mike James who wrote a series of "Intermediate C" articles in
UK Computer Shopper around 1984-5. One of these articles went into great
detail as to how expressions like this are evaluated e.g. given that j
starts as 1 then he spends half a column explaining why

x = j++ + --j;

ends up with x==2 and j==1. He then goes on to explain that

x = 10;
printf("%d,%d",--x,--x)

will output 8,9. Unfortunately few of the other articles in the series were
much better.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------


John Rixon

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
Helmut Leitner (lei...@hls.via.at) wrote:
:
: IMHO the really interesting questions are:
:
: 2. Why was the only natural solution:

:
: i = ++j * ++j;
:
: shall have the same result as
:
: ++j; ++j;
: i=j*j;
:
: (in a general form) never made part of the standard?

<yawn> Says who? Suppose j has an initial value of 5. Another ``natural
solution'' could be: ``What's the left operand of *? Answer [ah look, must
increment j] 6. What's the right operand of *? Answer [ah, increment j
again] 7. So, multiply 6 by 7.'' And what about something ghastly like
i=f(++j)*++j;, what would happen if f() modifies j? QEF. []. Hitler.

--
p..p..p..pick up a penguin: <www.uk.linux.org> jo...@areti.com
______________________________________________________________________________
char*o="Vxih $N",c;main(){int O,Q=2,C=*o+++144>>c++%Q;for(;Q--;putchar((O=5*(C
>>4*Q&3)+((O=C>>4*Q+2&3)?O+1:O))-3?O-18?O+97:64:46)-0x6d||puts(o))*o&&main();}

Mathew Hendry

unread,
Nov 7, 1998, 3:00:00 AM11/7/98
to
s...@eskimo.com (Steve Summit) wrote:

> In article <3644A64E...@hls.via.at>, Helmut Leitner
> <lei...@hls.via.at> writes:
> > 1. Why was this problem (as part of the subproblem to make C
> > easier to learn and use) never attacked?

[...]

> What is the natural interpretation of i = ++j * ++j?
> Is it
>
> ++j; ++j;
> i=j*j;
> or
> i = ++j;
> i *= ++j;
>
> or perhaps
>
> i = ++j;
> i *= j;
> ++j;
>
>I'm not claiming that the third interpretation is natural,
>but there are plenty of arguments in favor of the second one
>(especially if you're looking to express your rule for
>interpreting these in general form).

t1 = ++j;
t2 = ++j;
i = t1*t2;

is surely better as a general solution, or you'd get into trouble with
even simpler expressions such as

i = ++j * i;

But to give absolutely predictable results, you'd need to make some
rather UNnatural rules concerning order of evaluation. Consider

i = (j+=1) * (j+=2);

where (if we follow the above interpretation) the value assigned to
depends upon the order of evaluation of the side-effects of (j+=1) and
(j+=2). In the world outside of C, scalar multiplication is usually
considered to be commutative, so

i = (j+=1) * (j+=2);

should be equivalent to

i = (j+=2) * (j+=1);

Thus, it could be argued that expressions such as this should have
undefined - or at least unspecified - results because, in general,
they don't HAVE a natural interpretation. If you were to start
assigning them arbitrary interpretations, then you would almost
certainly make the language harder to understand, not easier.

-- Mat.


Dan Pop

unread,
Nov 8, 1998, 3:00:00 AM11/8/98
to

>Sorry guys , but i could not help compiling it. It compiles fine on AIX
>and the output is 20.

Let's see:

wgs01:~/tmp 57> uname
AIX
wgs01:~/tmp 58> cat test.c


main()
{
int i , j = 3;

i = ++j * ++j;

printf("%d\n", i);
}

wgs01:~/tmp 59> cc test.c
wgs01:~/tmp 60> ./a.out
25

Ah, the joys of undefined behaviour! :-)

Lawrence Kirby

unread,
Nov 8, 1998, 3:00:00 AM11/8/98
to
In article <3644A64E...@hls.via.at>
lei...@hls.via.at "Helmut Leitner" writes:

>rob wrote:
>>
>> Steve Summit wrote in message
>> >
>>
>> >> What is the output of the following C program ?

>> >> void main() {


>> >> int i , j = 3;
>> >> i = ++j * ++j;
>> >> printf("%d\n", i); }

>> >> P.S. dont compile it !!!
>> >
>> > Okay, without compiling it, I predict that the program will
>> > print "forty-two". Am I right?
>
>"zweiundvierzig" on my computer.
>
>> This hardly qualifies as the question of life, existence the
>> universe and everything
>

>IMHO the really interesting questions are:
>

>1. Why was this problem (as part of the subproblem to make C
> easier to learn and use) never attacked?

It was, and the rules you see are the result. It is a tradeoff between
close specification of the language and ease of optimisation.

>2. Why was the only natural solution:
>

> i = ++j * ++j;
>

> shall have the same result as
>
> ++j; ++j;
> i=j*j;
>
> (in a general form) never made part of the standard?

Because it is nonsense to say that this is the only natural solution. Also
why should the standard want to specify the behaviour of an exprerssion that
no C programmer should ever write? The real problem however is pointers.
Consider the expression

i = ++*p1 * ++*p2;

Here the problem occurs in the case when p1 and p2 point at the same object
and that cannot in general be determined at compile time. If the compiler
was forced to generate code that by some definition did the right thing
when p1==p2 that could seriously restrict its optimisation options.

>So that the old veterans can tease the newbees
>and have fun for the next 1000 years? :-)

The main problem here is that many books and tutorials don't explain this
area of the language properly or even correctly.

upp...@yahoo.com

unread,
Nov 9, 1998, 3:00:00 AM11/9/98
to
In article <71snve$3cg$1...@eskinews.eskimo.com>,

s...@eskimo.com (Steve Summit) wrote:
> In article <3641B4...@gec.nospam.com>, Edward Hill writes:
> >Alex Lemelev wrote:
> >> int i , j = 3;
> >> i = ++j * ++j;
> >
> > But well ++ has higher precedence than *
> > so I'd imagine j is incremented to 4 and then incremented
> > to 5 and then multiplied by itself to give 25.
> > So what's the answer?
>
> The answer, of course, is that there is no answer.
>

[snip]

> But it gets worse. The official wording in the ANSI/ISO C
> Standard says that if you attempt to modify the same object at
> one spot within an expression and refer to that same object at
> another spot (as in the expression ++j * j), or if you attempt
> to modify the same object twice within an expression (as in
> the expression ++j * ++j), the results are undefined [footnote 1].

My question is, why does the standard deem it an "undefined" expresion and not
as an "erroneous" one? Given that one can't assume anything about it, why
should the program continue to compile at all? I can understand undefined
states arising during the course of execution - such as when a NULL pointer is
free'ed - you simply can't catch it at compile time. But this (specifically,
the case where an lvalue is modified twice or modified and referenced between
sequence points) must be simple to catch at compile time, or am I being naive?

> What this means is that the compiler isn't even required to
> choose among the two (or six, or however many you can come up
> with) "plausible" interpretations of the expression; it can do
> any random thing it wants to, and it won't be in violation of the
> Standard. (In practice, it's not so much that compilers do "any

Which makes the Standard that much less useful...

[snipped out]

Mathew Hendry

unread,
Nov 9, 1998, 3:00:00 AM11/9/98
to
upp...@yahoo.com wrote:

[i = ++j * ++j]

: My question is, why does the standard deem it an "undefined" expresion and not


: as an "erroneous" one? Given that one can't assume anything about it, why
: should the program continue to compile at all? I can understand undefined
: states arising during the course of execution - such as when a NULL pointer is
: free'ed

(It is perfectly legal to call free on a null pointer)

: - you simply can't catch it at compile time. But this (specifically,


: the case where an lvalue is modified twice or modified and referenced between
: sequence points) must be simple to catch at compile time, or am I being naive?

Consider

int f(int *i, int *j) {
return ++(*i) * ++(*j);
}

and miles away, in some other source file

int x=5, y;
y = f(&x,&x);

So it's not so simple. In general, it's nigh-on impossible.

-- Mat.


lei...@my-dejanews.com

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
In article <722dsb$4rs$1...@eskinews.eskimo.com>,

s...@eskimo.com (Steve Summit) wrote:
> In article <3644A64E...@hls.via.at>, Helmut Leitner
> <lei...@hls.via.at> writes:
> > 1. Why was this problem (as part of the subproblem to make C
> > easier to learn and use) never attacked?
>
> Well, to be brutally frank and honest: The subproblem of making
> C easier to learn or use has never been attacked, nor (as far as
> I know) have either of these ever been goals of C.

Don't expect me to be shocked. BTW it doesn't matter, whether these
goals have been explicitly formulated or not. They are present in
any product development implicitly.

> > 2. Why was the only natural solution:
> > i = ++j * ++j;
> > shall have the same result as
> > ++j; ++j;
> > i=j*j;
> > (in a general form) never made part of the standard?
>

> I'm quite willing to address that question, but first we have to
> answer a sub-question (which Mathew Hendry has already reminded
> us of):
>

> What is the natural interpretation of i = ++j * ++j?
> Is it
>
> ++j; ++j;
> i=j*j;
> or
> i = ++j;
> i *= ++j;
>
> or perhaps
>
> i = ++j;
> i *= j;
> ++j;
>
> I'm not claiming that the third interpretation is natural,
> but there are plenty of arguments in favor of the second one
> (especially if you're looking to express your rule for
> interpreting these in general form).

IMHO the first form is the simplest both to the user
and the implementor.
You could
1. filter out all 'precrements' and 'postcrements'
2. execute all precrements
3. execute the original statement with
precrements and postcrements removed
4. execute all postcrements
and never talk about execution order.

Even more complicated expressions like

tab[i]= (++i +5) * tab[i++] * (--i -2);

would become simple to interpret:

++i; --i;
tab[i]=(i+5)*tab[i]*(i-2);
i++;

Quick and dirty.
Can't you feel some of the 'spirit of C' in this? :-)

Helmut Leitner
lei...@hls.via.at

Sorry, I had to (first time) use dejanews to post this,
because my provider's newsfeed is down. Hope it works.

nick.k...@gecm.com

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
for vanishingly small values of "interesting"


In article <01be08ba$4b7439c0$ec19...@lalex.ecitele.com>,
"Alex Lemelev" <Alex.L...@ecitele.com> wrote:

> What is the output of the following C program ?
>
> void main()
> {

> int i , j = 3;
>

> i = ++j * ++j;

> printf("%d\n", i);
> }

what do you *think* the answer is?

>
> P.S. dont compile it !!!
>

I can't

Brad Rogers

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
assuming your compiler initializes i = 0, it looks like ++j becomes 4 then
++j again becomes 5 since ++j is pre increment so the answer is 20

Steve Summit

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
In article <726taq$6ek$1...@nnrp1.dejanews.com>, upp...@yahoo.com writes:
>In article <71snve$3cg$1...@eskinews.eskimo.com>,

>s...@eskimo.com (Steve Summit) wrote:
>> But it gets worse. The official wording in the ANSI/ISO C
>> Standard says that if you attempt to modify the same object at
>> one spot within an expression and refer to that same object at
>> another spot (as in the expression ++j * j), or if you attempt
>> to modify the same object twice within an expression (as in
>> the expression ++j * ++j), the results are undefined [footnote 1].
>
> My question is, why does the standard deem it an "undefined" expresion
> and not as an "erroneous" one? Given that one can't assume anything
> about it, why should the program continue to compile at all? I can
> understand undefined states arising during the course of execution -
> such as when a NULL pointer is free'ed - you simply can't catch it at

> compile time. But this (specifically, the case where an lvalue is
> modified twice or modified and referenced between sequence points)
> must be simple to catch at compile time, or am I being naive?

Just a bit. The much more difficult (and in fact essentially
impossible, in full generality) cases to handle are those in
which the lvalue being modified twice is referred to in two
different ways, e.g. by pointers which we're not sure are the
same or different. If we have ++*p1 * ++*p2, then the expression
is okay if p1 != p2, but undefined if p1 == p2.

I agree, though, that a good compiler or lint ought to warn about
the "obvious" problems. Expressions which invoke undefined
behavior but which do not involve pointers, such as the
expression that started this thread, are:

the ones which do typically come up in "beginning" code
written by programmers who are best in a position to
learn from a well-chosen error message; and are

the ones which do tend to come up in these discussions;
and finally are

quite easy for a compiler to diagnose.

(I've got some code for doing so which I wrote as part of a
version of lint I tried to write once; perhaps I should try
integrating it into gcc -Wall some day.)

>> What this means is that the compiler isn't even required to
>> choose among the two (or six, or however many you can come up
>> with) "plausible" interpretations of the expression; it can do
>> any random thing it wants to, and it won't be in violation of the
>> Standard. (In practice, it's not so much that compilers do "any
>
> Which makes the Standard that much less useful...

Well, that's debatable. The standard rejoinder is that in most
cases, at least (and certainly in the case under discussion), the
expressions which the Standard labels as "undefined" are so bogus
that no sane programmer would ever write them, such that it
doesn't matter so much whether they're labeled as "illegal" or
"undefined".

On the other hand, if one cares about rigorous, formal
specification, it can certainly be argued that every instance
of behavior labeled as "undefined" represents a blemish (if not
an outright defect) in a Standard. If we categorize programs
or program fragments as being either well-defined, undefined,
or illegal, we'd like to keep the class of undefined programs
as small as possible; ideally, every program would either be
well-defined or else elicit at least one error message.
I've heard it claimed (by someone who was presumably in a better
position to make such characterizations than I) that the "gulf of
undefined behavior" is particularly wide in C, as opposed to
other languages.

Steve Summit
s...@eskimo.com

John Rixon

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
Brad Rogers (rog...@home.com) wrote:

: > > What is the output of the following C program ?
: > >
: > > void main()
: > > {
: > > int i , j = 3;
: > >
: > > i = ++j * ++j;
: > > printf("%d\n", i);

: > > }

: assuming your compiler initializes i = 0, it looks like ++j becomes 4


: then ++j again becomes 5 since ++j is pre increment so the answer is 20

<growl> Please tell me that you're a troll. Did you not read the previous
articles in this thread?

Daniel Barker

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
An interesting solution: only allow use of "++" through a macro that
increments its parameter and then casts its value to void.

/* macro to replace "++" */
#define inc(x) ((void) ((x)++))

main()
{
int x = 0;

inc(x);
printf("%d\n", x);

/* The following two lines are WRONG */
printf("%d\n", x = inc(x));
printf("%d\n", inc(x) * inc(x));
/* The above two lines are WRONG and will typically cause
* compilation to fail. They are wrong because the value of
* inc(x) is void, i.e., does not exist. (And as such cannot be
* printed using the "%d" format specifier. Though terrible, this
* is not the largest problem in either line. The largest problem
* is trying to use the value of inc(x) for anything at all.) */
return 0;
}

Since inc(x) has no value, the value must not be used. Compilers seem good
at detecting attempts to use a void value, much better than they are at
detecting errors of the kind *p = (*p)++. I can see minor objections to
inc(), but it seems on the whole to provide real benefits.

Problems with inc() include:

1. It cannot help if the user tries something like

x = (x = x + 1) /* BAD, WRONG */

2. It looks like a function with call by value.

Advantages of using inc() instead of ever directly using "++" include:

1. It directly reduces opportunities for bugs;

2. It makes the program source clearer by reducing opportunities for
convoluted constructs.


Daniel Barker,
Institute of Cell and Molecular Biology,
Swann Building,
King's Buildings,
Mayfield Road,
Edinburgh
EH9 3JR
UK


Daniel Barker

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
On Tue, 10 Nov 1998, some fool wrote:

> An interesting solution: only allow use of "++" through a macro that
> increments its parameter and then casts its value to void.
>
> /* macro to replace "++" */
> #define inc(x) ((void) ((x)++))
>
> main()
> {
> int x = 0;
>
> inc(x);
> printf("%d\n", x);

[snip]

Of course, the above implicit declaration of variadic function printf() is
a terrible bug with which inc() CANNOT help ...

john...@tivoli.com

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
In article <355CC057...@home.com>,

Brad Rogers <rog...@home.com> wrote:
> assuming your compiler initializes i = 0, it looks like ++j becomes 4 then
> ++j again becomes 5 since ++j is pre increment so the answer is 20
>

So what about Dan's machine giving an answer of 25?

Refer to the other articles in this thread by Steve, Lawrence, or Dan to
understand why your reasoning is meaningless in this situation.

Just because it compiled, ran, and gave you an answer doesn't mean that the
answer is right (in this case, there is *no* right answer, but myriad wrong
ones).

> nick.k...@gecm.com wrote:
>
> > for vanishingly small values of "interesting"
> >

<giggle>

Dan Pop

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
In <72a8c3$35f$1...@nnrp1.dejanews.com> john...@tivoli.com writes:

>Just because it compiled, ran, and gave you an answer doesn't mean that the
>answer is right (in this case, there is *no* right answer, but myriad wrong
>ones).

It's the other way 'round: in this case, there is *no* wrong answer, but
a myriad of right ones. The code is wrong, the answers *are* correct,
because anything you get as the result of undefined behaviour is, by
definition, correct (i.e. it does not violate the language definition).

Joe Maun

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to

Daniel Barker wrote:
>
> An interesting solution: only allow use of "++" through a macro that
> increments its parameter and then casts its value to void.
>
> /* macro to replace "++" */
> #define inc(x) ((void) ((x)++))
>
> main()
> {
> int x = 0;

int i = inc(x); /*oops - should be legal*/

I wouldn't call this a "solution".

--
Joe

Dann Corbit

unread,
Nov 10, 1998, 3:00:00 AM11/10/98
to
Dissenting opinion: BLEAH!
And I see no protection whatever from:
x = inc(i);
or even:
x = inc(x);
Is this a joke, or what?
--
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ ftp: ftp://rtfm.mit.edu, C-FAQ Book: ISBN 0-201-84519-9
Try "C Programming: A Modern Approach" ISBN 0-393-96945-2

Daniel Barker

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to

It is a solution in the sense that it restricts use of an error-prone
language feature, without reducing what you can achieve in your program.
Cf. an in-house coding standard that bans "goto" entirely, except for
error handling. (I don't know of a standard that does this, it's just an
example, though I expect there is at least one such standard somewhere.)

If you only ever access "++" through the "inc()" macro, you have to write
the code, as, for example (if you're after "i = x++"):

i = x;
inc(x);

Or, if you're after "i = ++x", like this:

inc(x);
i = x;

I think this will usually make the source code easier to follow. As well
as reduced bugs from sequence-point trouble, the programmer's brain is
un-burdened, since it no longer has to recal the difference between "++i"
and "i++". But my proposed approach is somewhat outside the C tradition.

I have not tried my "inc()" in any important program, since I only thought
of it yesterday.

It certainly looks OK for "for" loops, for example:

for ( n = 0; n < NKEYS; inc(n) )

and for at least some "while" loops, for example:

while ( (*s1 = *s2) != '\0' )
{
inc(s1);
inc(s2);
}

and for at least some "do" loops, for example:

do
{
s[i] = n % 10 + '0';
inc(i);
} while ( ( n /= 10 ) > 0 );

These examples are based on some programs in K&R2, altered to use "inc()"
instead of "++". E&OE.

Chris Kuan

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Steve Summit wrote:

> I agree, though, that a good compiler or lint ought to warn about
> the "obvious" problems.

> (...) in most


> cases, at least (and certainly in the case under discussion), the
> expressions which the Standard labels as "undefined" are so bogus
> that no sane programmer would ever write them, such that it
> doesn't matter so much whether they're labeled as "illegal" or
> "undefined".
>
> On the other hand, if one cares about rigorous, formal
> specification, it can certainly be argued that every instance
> of behavior labeled as "undefined" represents a blemish (if not
> an outright defect) in a Standard. If we categorize programs
> or program fragments as being either well-defined, undefined,
> or illegal, we'd like to keep the class of undefined programs
> as small as possible; ideally, every program would either be
> well-defined or else elicit at least one error message.
> I've heard it claimed (by someone who was presumably in a better
> position to make such characterizations than I) that the "gulf of
> undefined behavior" is particularly wide in C, as opposed to
> other languages.

There was a mini-thread in comp.lang.eiffel a couple of
months ago about just this topic. Given the inertia of
the C programming language, it became rather a moot point.


--

Chris Kuan, BHP Information Technology
Concatenate for email: mr gazpacho @ hotmail . com
Phone : +61 2 4275 5555 Fax : +61 2 4275 5547

"A Design Pattern is something that got left out of the language"
- Richard O'Keefe

Daniel Barker

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
On Tue, 10 Nov 1998, Dann Corbit wrote:

> Dissenting opinion: BLEAH!
> And I see no protection whatever from:
> x = inc(i);
> or even:
> x = inc(x);
> Is this a joke, or what?

For those who have lost the original, and if I have put the above in the
right context, inc() is:

#define inc(x) ((void) ((x)++))

So, both your assignments to x above are in error, because "the
(nonexistent) value of a void object may not be used in any way, and
neither explicit nor implicit conversion to any non-void type may be
applied" (K&R2, Section A6.7).

The point of inc() is that I would be surprised if anyone could get

x = inc(i);

past the compiler. In which case, the following is also ruled out:

x = inc(x);

So if, by means of programmer discipline, "++" is outlawed entirely other
than in the definition of inc(), the errors

x = x++;

and

x = ++x;

become impossible. Yet it is not conveniently incrementing an lvalue that
has been ruled out to achieve this: rather, the route by which this is
done has been constrained.

Brad Rogers

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
So the answer is 25. The question said dont compile it so I didnt!

thanks for the polite response. this is bad programming style and I dont use it.
After closer inspection, ++ associates right to left and takes precedence, so the
2 j variables were just incremented twice then multiplied. Simple. Just as

int i, j = 3;

i = j * ++j;

the answer is 16, not 3 * 4

perhaps thats why its an interesting question. So I forgot to read the precedence
chart and assumed. I dont think I forgot when I programmed the nuclear reactor
control program.

john...@tivoli.com wrote:

> In article <355CC057...@home.com>,
> Brad Rogers <rog...@home.com> wrote:
> > assuming your compiler initializes i = 0, it looks like ++j becomes 4 then
> > ++j again becomes 5 since ++j is pre increment so the answer is 20
> >
>
> So what about Dan's machine giving an answer of 25?
>
> Refer to the other articles in this thread by Steve, Lawrence, or Dan to
> understand why your reasoning is meaningless in this situation.
>

> Just because it compiled, ran, and gave you an answer doesn't mean that the
> answer is right (in this case, there is *no* right answer, but myriad wrong
> ones).
>

Stephan Wilms

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Daniel Barker wrote:
>
> Cf. an in-house coding standard that bans "goto" entirely, except for
> error handling. (I don't know of a standard that does this,

I do ! I've banned the use of "goto" entirely and no one has dared
to defy me yet. And it works, too. We found out that we can live
and program quite happily and successsfully without using "goto" at all.

(And if I ever see one, the corresponding programmer will become
very unhappy very fast ;-)

Stephan
(initiator of the campaign against grumpiness in c.l.c)

Martin Ambuhl

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Brad Rogers wrote:
>
> So the answer is 25.

No it's not. It's 17, 4932, and "Yo mamma". Haven't you learned
anything from this thread.

> The question said dont compile it so I didnt!

You don't compile it because it is illegal code.

>
> thanks for the polite response. this is bad programming style and I dont use it.

It is always "bad programming style" to write illegal code.

> After closer inspection, ++ associates right to left and takes precedence,

Precedence is irrelevant. Read the FAQ, please.

>so the
> 2 j variables were just incremented twice then multiplied. Simple. Just as
>
> int i, j = 3;
>
> i = j * ++j;
>
> the answer is 16, not 3 * 4
>
> perhaps thats why its an interesting question. So I forgot to read the precedence
> chart and assumed. I dont think I forgot when I programmed the nuclear reactor
> control program.

Where is this nuclear reactor? Any sane person will move away from it
quickly if you wrote code controlling it.

--
Martin Ambuhl (mam...@earthlink.net)
Note: mam...@tiac.net will soon be inactive


Lawrence Kirby

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
In article <355C6671...@home.com> rog...@home.com "Brad Rogers" writes:

>So the answer is 25.

No, it isn't. 25 is an answer because any answer is correct. The construct
results in undefined behaviour which means that anything is allowed to
happen as a result of executing the code. 25 is just one valid way of
implementing anything. Anothing is having the program crash.

> The question said dont compile it so I didnt!

The problem is that if you compile and get an answer you might falsely
assume that that is the only correct answer.

>thanks for the polite response. this is bad programming style and I dont use
> it.

>After closer inspection, ++ associates right to left and takes precedence, so


> the
>2 j variables were just incremented twice then multiplied. Simple. Just as
>
>int i, j = 3;
>
>i = j * ++j;
>
>the answer is 16, not 3 * 4

Again, any answer is correct. Different compiler can and do produce different
results. The problem stems from when the side-effect is evaluated and
precedence and associativity have no bearing on that, side-effects are
only constrained by sequenmce points.

>perhaps thats why its an interesting question. So I forgot to read the
> precedence
>chart and assumed. I dont think I forgot when I programmed the nuclear reactor
>control program.

The point is that it is an error to write this sort of code at all, especially
for a nuclear reactor!

Stephan Wilms

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Brad Rogers wrote:
>
> So the answer is 25. The question said dont compile it so I didnt!

No it is not !!! There is no single answer. Each C compiler *might*
give a totally different answer, because the ANSI-C standard has
declared this expression as being *UNDEFINED*.

> thanks for the polite response. this is bad programming style and I dont use it.

It is totally wrong programming style, as it tends to produces
more or less randomly wrong results.

> After closer inspection, ++ associates right to left and takes precedence, so the
> 2 j variables were just incremented twice then multiplied. Simple.

Hmmm, this is a rather complex subject, but you have been presented
with a lot of rather good explanations. Why do you refuse to
understand ?

> Just as
>
> int i, j = 3;
>
> i = j * ++j;
>
> the answer is 16, not 3 * 4

Aaargh ! NO the is (again) NO correct answer. ANSI-C *guaraties*
that the result is UNDEFINED ! One compiler might give 16, another 12,
the next 42. As far as undefined behaviour is concerned your program
might crash at this point.

Stephan
(initiator of the campaign against grumpiness in c.l.c)

(no, I'm not grumpy, juyt mildly annoyed)

raw...@my-dejanews.com

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
In article <3648D887...@yahoo.com>,

Joe Maun <repl...@yahoo.com> wrote:
>
>
> Daniel Barker wrote:
> >
> > An interesting solution: only allow use of "++" through a macro that
> > increments its parameter and then casts its value to void.

A better way of enforcing such a coding standard might be to modify
the compiler to give diagnostics if the value returned by ++ were
used in a larger expression; then the code would still be readable
(if verbose) for programmers unfamiliar with the inc macro. (It would
also help to state more precisely what this is a solution to.)

> > /* macro to replace "++" */
> > #define inc(x) ((void) ((x)++))
> >
> > main()
> > {
> > int x = 0;
>
> int i = inc(x); /*oops - should be legal*/
>
> I wouldn't call this a "solution".

That depends on what the problem is.

In general, having all operators with side effects result in void
would solve many problems caused by the order (or lack thereof)
of side effects, since there would be at most one side effect, occuring
with the last operator evaluated. (There would be no result to use
in further expressions.) Unfortunately it would also eliminate common
C idioms like a=b=c=0; and while((c=getchar()) != EOF).

Languages that do not allow assignment expressions (having only
assignment statements) have essentially applied this to the = operator.
(Languages with assignment expressions have been shown to be
more error prone than those with assignment statements.) This also
raises questions about side effects in functions that don't return void,
since order of evaluation problems still exist with these; the impending
dominance of the programming language Euclid will of course answer
all of these questions.

--
MJSR

Dan Pop

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
I haven't seen Steve's post, so I'm commenting the text included in
Chris Kuan's post.

In <3648EA...@sig.please> Chris Kuan <lo...@sig.please> writes:

>Steve Summit wrote:
>
>> On the other hand, if one cares about rigorous, formal
>> specification, it can certainly be argued that every instance
>> of behavior labeled as "undefined" represents a blemish (if not
>> an outright defect) in a Standard.

It's also what makes C so powerful and popular.

>> If we categorize programs
>> or program fragments as being either well-defined, undefined,
>> or illegal, we'd like to keep the class of undefined programs
>> as small as possible; ideally, every program would either be
>> well-defined or else elicit at least one error message.

By the time you reach this point, C would be a dead language. There
are lots of extremely useful things that can be done in C, but which
cannot be well defined by the standard.

Wouldn't you hate to see a diagnostic every time you included <unistd.h>?

The approach followed by the Standard is the right one: standardize what
can be standardized and leave the rest undefined. From the very
beginning, C was the language to get things done, not to please the guys
who love rigorous, formal specifications but don't have to solve real
world problems.

Having to choose between a language which does not allow me to solve
a problem and a language which does not allow me to solve the same problem
in a portable way, I'd choose the latter, without a second's hesitation.

>> I've heard it claimed (by someone who was presumably in a better
>> position to make such characterizations than I) that the "gulf of
>> undefined behavior" is particularly wide in C, as opposed to
>> other languages.

And this is precisely why C is more popular than the other languages, with
narrower "gulfs of undefined behavior". A wider gulf means a wider class
of problems that can be solved in that language. Again, it's the choice
between no solution at all and a non-portable solution.

Dan Pop

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
In <36494A...@CWA.de> Stephan Wilms <Stepha...@CWA.de> writes:

>Daniel Barker wrote:
>>
>> Cf. an in-house coding standard that bans "goto" entirely, except for
>> error handling. (I don't know of a standard that does this,
>
>I do ! I've banned the use of "goto" entirely and no one has dared
>to defy me yet. And it works, too. We found out that we can live
>and program quite happily and successsfully without using "goto" at all.
>
>(And if I ever see one, the corresponding programmer will become
>very unhappy very fast ;-)

So, in your opinion, Ritchie was badly mistaken when he decided that goto
is a good thing and worth putting into the language.

There are cases when avoiding goto at all costs generates virtually
unreadable "structured" code.

Banning goto makes as much sense as banning a tool from your toolbox
because it is very sharp and you can do the same job with a blunt one,
if you work ten times harder.

The good programmer has understood the difference between use and abuse
and has replaced dogmatism by pragmatism.

J. Benz

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to

Stephan Wilms wrote:

> Daniel Barker wrote:
> >
> > Cf. an in-house coding standard that bans "goto" entirely, except for
> > error handling. (I don't know of a standard that does this,
>
> I do ! I've banned the use of "goto" entirely and no one has dared
> to defy me yet. And it works, too. We found out that we can live
> and program quite happily and successsfully without using "goto" at all.
>
> (And if I ever see one, the corresponding programmer will become
> very unhappy very fast ;-)

Yes indeed - if you gotta goto, you gotta go too.


J. Benz

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to

Dan Pop wrote:

> So, in your opinion, Ritchie was badly mistaken when he decided that goto
> is a good thing and worth putting into the language.
>

If you bother to read the pertinent section in the original edition of the
K&R book (pre ANSI, copyright 1978, Bell Labs) you'll find this disclaimer:

"C provides the infinitely abusable goto statement, and labels to branch to.
Formally, the goto is never necessary, and in practice it is always easy to
write code without it. We have not used goto in this book."

and

"Although we are not dogmatic about the matter, it does seem that goto
statements should be used sparingly, if at all."

Seems pretty clear to me that goto was included in the language against the
better judgement of the authors, probably because most programmers of the day
felt naked without it. It also seems pretty clear that DMR and BWK didn't
consider goto a 'good thing' at all.


Billy Chambless

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
In article <3649CF3C...@danet.com>, "J. Benz" <be...@danet.com> writes:


|> Dan Pop wrote:

|> > So, in your opinion, Ritchie was badly mistaken when he decided that goto
|> > is a good thing and worth putting into the language.


|> If you bother to read the pertinent section in the original edition of the

I'll bet you 97 rubles that Dan has, in fact, read the text you quoted.

|> K&R book (pre ANSI, copyright 1978, Bell Labs) you'll find this disclaimer:

|> "C provides the infinitely abusable goto statement, and labels to branch to.
|> Formally, the goto is never necessary, and in practice it is always easy to
|> write code without it. We have not used goto in this book."

|> and

|> "Although we are not dogmatic about the matter, it does seem that goto
|> statements should be used sparingly, if at all."

Did you happen to read the text in between the parts you quoted -- the part that
begins, "Nevertheless, there are a few situations where gotos may find a place."?

|> Seems pretty clear to me that goto was included in the language against the
|> better judgement of the authors, probably because most programmers of the day
|> felt naked without it. It also seems pretty clear that DMR and BWK didn't
|> consider goto a 'good thing' at all.

Did you happen to read the text in between the parts you quoted -- the part that
begins, "Nevertheless, there are a few situations where gotos may find a place."?

Seems pretty clear to me that they thought it wa a useful feature, albeit one that shouldn't be used very often.

Yes, the goto is infinitely-abuseable; but then, so are pointers, the ternary logical operator, the return statement, etc.

--
"Unix *is* Perl's IDE!"
-- Tom Christiansen

William Roeder

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Lawrence Kirby wrote:
>
> In article <355C6671...@home.com> rog...@home.com "Brad Rogers" writes:
<snip>

> >perhaps thats why its an interesting question. So I forgot to read the
> > precedence
> >chart and assumed. I dont think I forgot when I programmed the nuclear reactor
> >control program.
>
> The point is that it is an error to write this sort of code at all, especially
> for a nuclear reactor!
<snip>
IMNSHO a nuclear reactor is an error.

Adam Fordyce

unread,
Nov 11, 1998, 3:00:00 AM11/11/98
to
Daniel Barker wrote:
[in regards to a macro to replace the ++ operator with inc()]

>
> It is a solution in the sense that it restricts use of an error-prone
> language feature, without reducing what you can achieve in your program.
> Cf. an in-house coding standard that bans "goto" entirely, except for
> error handling. (I don't know of a standard that does this, it's just an
> example, though I expect there is at least one such standard somewhere.)
>
> If you only ever access "++" through the "inc()" macro, you have to write
> the code, as, for example (if you're after "i = x++"):
>
> i = x;
> inc(x);
>
> Or, if you're after "i = ++x", like this:
>
> inc(x);
> i = x;
>
> I think this will usually make the source code easier to follow. As well
> as reduced bugs from sequence-point trouble, the programmer's brain is
> un-burdened, since it no longer has to recal the difference between "++i"
> and "i++".

Erm, since when has the difference between i++ and ++i put an undue
burden on the programmers brain? Surely, anyone who has been coding for
more than, what, five minutes, is in a position to use and understand
the postfix and prefix operators without getting too bogged down. In
regards to the earlier statement, I don't recall the increment operator
as being "error-prone".

As for your opinions regarding the goto statement, it looks to me like
you have read K&R, heard lots of people (who have also read it) saying
how bad "goto" is and have decided it *must* be a bad thing if all these
people agree! It's easy to understand why. I mean, imagine the flaming
someone would receive if he/she had the guts to write an article
explaining how prevalent the word "goto" was in the latest release of
their application. You hear stories of "unmanageable, spaghetti code"
but find that half the people who are so against poor old goto, have had
*extremely* limited programming experience; certainly not enough to
justify a valid opinion on the subject. Oh and before you reply telling
me how many years you have been hacking, I'm talking generally, not
specifically about your case ok?

Besides, people use goto statements all the time. I mean, what are the
"case:" statements of a switch statement if they aren't goto labels with
local scope? I've sometimes found goto useful when breaking from nested
loops, haven't you? Oh yeah, and assembly language is absolutely
chockablock with goto statements so they can't be all that bad *grin*.

Oh well, just my thoughts,

Adam

--
--------------------------------------------------------------
Homer: "First you don't want me to buy a pony, *then* you want
me to take it back; will you make up your mind!!!"
--------------------------------------------------------------

tst...@my-dejanews.com

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <3649CF3C...@danet.com>,

"J. Benz" <be...@danet.com> wrote:
>
>
> Dan Pop wrote:
>
> > So, in your opinion, Ritchie was badly mistaken when he decided that goto
> > is a good thing and worth putting into the language.
> >
>
> If you bother to read the pertinent section in the original edition of the
> K&R book (pre ANSI, copyright 1978, Bell Labs) you'll find this disclaimer:
>
> "C provides the infinitely abusable goto statement, and labels to branch to.
> Formally, the goto is never necessary, and in practice it is always easy to
> write code without it. We have not used goto in this book."
>
> and
>
> "Although we are not dogmatic about the matter, it does seem that goto
> statements should be used sparingly, if at all."
>
> Seems pretty clear to me that goto was included in the language against the
> better judgement of the authors, probably because most programmers of the day
> felt naked without it. It also seems pretty clear that DMR and BWK didn't
> consider goto a 'good thing' at all.
>
>

But they *did* include it.

The following contains heretical statements.

K&R are not Gods, you do not have to take whatever they say as absolute truth.

--
Tristan Styles

Failure is not an option
It is Standard Operating Procedure

Jens Schweikhardt

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
Dan Pop <Dan...@cern.ch> wrote:
# In <36494A...@CWA.de> Stephan Wilms <Stepha...@CWA.de> writes:

#>Daniel Barker wrote:
#>>
#>> Cf. an in-house coding standard that bans "goto" entirely, except for
#>> error handling. (I don't know of a standard that does this,
#>
#>I do ! I've banned the use of "goto" entirely and no one has dared
#>to defy me yet. And it works, too.

It does, Stephan? Here's a challenge for you: Write the tcp_input()
function without goto. It's part of virtually every OS out there on
the net. You can find it on every ftp server near you, e.g.
ftp://ftp.apfel.de/pub/FreeBSD/FreeBSD-stable/src/sys/netinet/tcp_input.c

The implementation follows a non trivial state machine, see
ftp://ftp.uni-stuttgart.de/pub/doc/standards/rfc/RFC700/rfc793.txt.gz

Now if you take a specification like RFC793 to start from, an extremely
precise spec BTW (in the detail you dream of as a programmer), then you
thank God in Heaven as well as Dennis for goto. Let's look at an example:
(just a tiny snippet)

[page 75]
SYN-RECEIVED STATE
ESTABLISHED STATE

Enter the CLOSE-WAIT state.

FIN-WAIT-1 STATE

If our FIN has been ACKed (perhaps in this segment), then
enter TIME-WAIT, start the time-wait timer, turn off the other
timers; otherwise enter the CLOSING state.
...

It's easier to follow this precise specification if you can say (pseudo C)

switch (state) {

case SYN-RECEIVED STATE:
case ESTABLISHED STATE:
goto CLOSE-WAIT state;

case FIN-WAIT-1 STATE:

if (our FIN has been ACKed)
goto TIME-WAIT;
else
goto CLOSING;
...
}

Try to do this without goto (sure, it can be done on a theoretical basis).
But would you be sure your code does what the spec requires?

# We found out that we can live
#>and program quite happily and successsfully without using "goto" at all.

Lucky one. You don't do TCP implementations :-)

#>(And if I ever see one, the corresponding programmer will become
#>very unhappy very fast ;-)

# So, in your opinion, Ritchie was badly mistaken when he decided that goto
# is a good thing and worth putting into the language.

# There are cases when avoiding goto at all costs generates virtually
# unreadable "structured" code.

That hits the nail on the head.

# Banning goto makes as much sense as banning a tool from your toolbox
# because it is very sharp and you can do the same job with a blunt one,
# if you work ten times harder.

# The good programmer has understood the difference between use and abuse
# and has replaced dogmatism by pragmatism.

GIWIST! (Gee, I wish I'd said that)

Regards,

Jens
--
Jens Schweikhardt http://www.shuttle.de/schweikh/
SIGSIG -- signature too long (core dumped)

Lawrence Kirby

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <72c6n9$lqs$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:

...

>In general, having all operators with side effects result in void
>would solve many problems caused by the order (or lack thereof)
>of side effects, since there would be at most one side effect, occuring
>with the last operator evaluated. (There would be no result to use
>in further expressions.) Unfortunately it would also eliminate common
>C idioms like a=b=c=0; and while((c=getchar()) != EOF).

Not to mention a[i++] and *p++

>Languages that do not allow assignment expressions (having only
>assignment statements) have essentially applied this to the = operator.
>(Languages with assignment expressions have been shown to be
>more error prone than those with assignment statements.)

Maybe, but I suspect that the effect is marginal. The main problem in
C seems to be with the form of the operator with = getting mixed up with ==.
IMO it would have been better if C had used something like := for assignment.
Seeing that in the middle of an expression would be more surprising (it
would stand out more) which is how it should be. Of course it is far too
late to change that now.

Lawrence Kirby

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <3649CF3C...@danet.com> be...@danet.com "J. Benz" writes:

>
>
>Dan Pop wrote:
>
>> So, in your opinion, Ritchie was badly mistaken when he decided that goto

>> is a good thing and worth putting into the language.
>>
>

>If you bother to read the pertinent section in the original edition of the
>K&R book (pre ANSI, copyright 1978, Bell Labs) you'll find this disclaimer:
>
>"C provides the infinitely abusable goto statement, and labels to branch to.
>Formally, the goto is never necessary, and in practice it is always easy to
>write code without it. We have not used goto in this book."
>
>and
>
>"Although we are not dogmatic about the matter, it does seem that goto
>statements should be used sparingly, if at all."
>
>Seems pretty clear to me that goto was included in the language against the
>better judgement of the authors, probably because most programmers of the day
>felt naked without it. It also seems pretty clear that DMR and BWK didn't
>consider goto a 'good thing' at all.

You could also argue that K&R included this text to deflect criticism from
the structured programming fanatics of the time (and there really were
fanatics, much more so than now). Of course neither of these interpretations
alone tells the whole story.

Stephan Wilms

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
Dan Pop wrote:
>
> In <36494A...@CWA.de> Stephan Wilms <Stepha...@CWA.de> writes:
>
> >I do ! I've banned the use of "goto" entirely and no one has dared
> >to defy me yet. And it works, too. We found out that we can live

> >and program quite happily and successsfully without using "goto" at all.
>
> >(And if I ever see one, the corresponding programmer will become
> >very unhappy very fast ;-)
>
> So, in your opinion, Ritchie was badly mistaken when he decided that goto
> is a good thing and worth putting into the language.

From my current point of view: yes. But I admit that this point of
view does not encompass the whole area of C programming. There might
indeed be uses for it, as indicated below.

> There are cases when avoiding goto at all costs generates virtually

> unreadable "structured" code.

This is probably true, especially if you say it ;-)
In the area where we work my banning aproach has worked out for some
6 years so far with not so much as a trace of a good use for goto (yet).
Actually I am not really a tough hardliner at all. If someone explains
to me a good reason for using a "goto", I will probably let it be. The
problem is that (IMHO) free use of "goto" can do a lot of damage to
the code. I have seen and written my own share of BASIC code

I can not dispute the fact that "goto" can be used in an acceptable
way and will make some specific constructs more readable. That's
why talking about the use of "goto" is such an inflamatory subject.
But I do hold the opinion that the damage potential of "goto" is
high enough to justify banning it.

> Banning goto makes as much sense as banning a tool from your toolbox

> because it is very sharp and you can do the same job with a blunt one,

> if you work ten times harder.

It all depends on what kind of tool or object we talk about. A lot
of countries have banned things like firearms or specific potentially
dangerous drugs or powerful explosives, despite their usefulness in
certain cases. It's all a matter of relationship: how does the
potential danger relate to the usefulness. Maybe this is a bit drastic.
Let's maybe compare "goto" to one of those ceramic kitchen knifes.
They are freely available (AFAIK) and very useful, because they are
sharp as hell. But they are also very dangerous, because they are
sharp as hell. If you get in contact with the sharp edge, you will
very likely cut yourself. And if you cut yourself while using the
knife you will almost certainly cut yourself deep and severely. And
if you drop the knife you will either cut your toe of or the knife
will shatter when it hits the floor, because ceramic is not very
flexible.

> The good programmer has understood the difference between use and abuse

> and has replaced dogmatism by pragmatism.

Yes, I agree with you: the *good* and experienced programmer
understands. But the good and experienced programmer should not
need coding guidelines at all and yet they tend to be quite useful.
I considered things like "do not use goto" and "do not use gets"
a useful addition to the coding guidelines. And they have not been
refuted by my collegues either. I'm not their boss, just the one
who was choosen to write and maintain the guidelines. And we discussed
the contents before they were promoted to company guideline status.

What I see as your main point of critique is that I used the phrase
"banned entirely". My collegues and I have decided that the "goto"
has so little use, that banning it is acceptable. I know that others
have made similar decisions.

But I understand that an absolute phrase like "banned entirely" can
be seen as being too restrictive. I respect this point of view. And
that's why I will not press this point any further. The use of "goto"
has always been the subject of heated debates.

raw...@my-dejanews.com

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <72e6jh$d2f$2...@news.BelWue.DE>,
Jens Schweikhardt <schw...@diamant.noc.dfn.de> dares to defy Stephan:
> # In <36494A...@CWA.de> Stephan Wilms <Stepha...@CWA.de> writes:
> #>
> #>I do ! I've banned the use of "goto" entirely and no one has dared
> #>to defy me yet. And it works, too.

Edsger W. Dijkstra, "Go To Statement Considered Harmful",
http://www1.acm.org:81/classics/oct95/
Donald Knuth, "Structured Programming with go to Statements",
Computing Surveys, Vol 6, No 4, December 1974

> The implementation follows a non trivial state machine, see
> ftp://ftp.uni-stuttgart.de/pub/doc/standards/rfc/RFC700/rfc793.txt.gz
>
> Now if you take a specification like RFC793 to start from, an extremely
> precise spec BTW (in the detail you dream of as a programmer), then you
> thank God in Heaven as well as Dennis for goto. Let's look at an example:
> (just a tiny snippet)
>
> [page 75]
> SYN-RECEIVED STATE
> ESTABLISHED STATE
>
> Enter the CLOSE-WAIT state.
>
> FIN-WAIT-1 STATE
>
> If our FIN has been ACKed (perhaps in this segment), then
> enter TIME-WAIT, start the time-wait timer, turn off the other
> timers; otherwise enter the CLOSING state.

The specification is already coded with goto's ("enter X state"); as
Dijkstra comments, "The exercise to translate an arbitrary flow diagram
more or less mechanically into a jump-less one, however, is not to be
recommended." It is a point in favor of goto's that some specifications
come this way, but I prefer to code a finite state machine as a switch
nested in a loop:

state = STARTING_STATE;
while (state != DONE_STATE)


> switch (state) {
>
> case SYN-RECEIVED STATE:
> case ESTABLISHED STATE:

state = CLOSE_WAIT; /* goto CLOSE-WAIT state; */
break;


>
> case FIN-WAIT-1 STATE:
>
> if (our FIN has been ACKed)

state = TIME_WAIT; /* goto TIME-WAIT; */
> else
state = CLOSING; /* goto CLOSING; */
break;


> ...
> }
>
> Try to do this without goto (sure, it can be done on a theoretical basis).
> But would you be sure your code does what the spec requires?

Yes. Are you sure the goto code does what the spec requires?

One advantage of the while-switch approach is that the set of states
can be listed as an enumeration and thus documented in one place,
and checked by the compiler (to the extent that C enumerations can
be checked). Another advantage is that it keeps Stephan happy.

--
MJSR

Stephan Wilms

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
Jens Schweikhardt wrote:

>
> Dan Pop <Dan...@cern.ch> wrote:
> # In <36494A...@CWA.de> Stephan Wilms <Stepha...@CWA.de> writes:
>
> #>I do ! I've banned the use of "goto" entirely and no one has dared
> #>to defy me yet. And it works, too.
>
> It does, Stephan? Here's a challenge for you: Write the tcp_input()
> function without goto. It's part of virtually every OS out there on
> the net. You can find it on every ftp server near you, e.g.

Hah, I remember seeing that challange before. I doubt that there is
a real solution without "goto" :-)

The "banned goto entirely" has stirred up emotions quite a bit.
Please understand that I did *not* bann it worldwide, and that this
is *not* my intention. It has been banned in the company coding
standard and that working great. For several years. I work mainly
on low level hardware drives (both ISR and polling) and on part
of the surrounding application layer. Neither I nor my collegues
working on other parts of the project or other projects have been
confronted with the need for using goto (yet).

The exceptions where the use of "goto" can be considered beneficial
are extremely rare. We decided to give it a try and bann some things
that we considered dangerous (like "goto" or "gets()") and it works
great so far.

Like Dan said: good programmer know about these things, but it does
not hurt to remind them.

> # We found out that we can live
> #>and program quite happily and successsfully without using "goto" at all.
>
> Lucky one. You don't do TCP implementations :-)

No, we don't. It's cardiology mainly. We've got a big system certified
for use in German hospitals a few days ago. I wrote the software for
the main digitising and preprocessing unit where the physician plugs
in the intracardial catheters (5 parallel processors, 9 parallel
processes) and I'm telling you all this because I DID NOT USE A
SINGLE GOTO AT ALL ! In fact the whole (big) system does not use
a single goto that I am aware of in the C part of the software.

> # There are cases when avoiding goto at all costs generates virtually
> # unreadable "structured" code.
>
> That hits the nail on the head.

And I agree with both of you on this point. But these cases are
exceedingly rare.

J. Benz

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to

tst...@my-dejanews.com wrote:

> In article <3649CF3C...@danet.com>,
> "J. Benz" <be...@danet.com> wrote:
> >
> >
> >

> > Seems pretty clear to me that goto was included in the language against the
> > better judgement of the authors, probably because most programmers of the day
> > felt naked without it. It also seems pretty clear that DMR and BWK didn't
> > consider goto a 'good thing' at all.
> >
> >
>

> But they *did* include it.
>
> The following contains heretical statements.
>
> K&R are not Gods, you do not have to take whatever they say as absolute truth.

This was not offered as a blood sacrifice either - willing virgins weren't
available. Merely a refutation to your contention, that their inclusion of goto in
the language was any kind of endorsement of the wisdom of its use - what better
evidence than the author's own words? What *you* endorse is your own problem.
Yeah, they *did* include it, but apparently they *didn't* like it. As for their
motives, why don't you call up Bell Labs and see if you can get DMR on the phone,
and ask him? It could be as simple as having one extra slot in the token table,
and they couldn't figure out what else to put into the language.

But we've strayed a little from the technical... and into the realm of trying to
guess the intent of people who aren't party to the discussion. A singularly futile
thing to do.

J. Benz

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to

William Roeder wrote:

> Lawrence Kirby wrote:
> >
> >
> > The point is that it is an error to write this sort of code at all, especially
> > for a nuclear reactor!
> <snip>
> IMNSHO a nuclear reactor is an error.

IMNSHO, the naivete and ignorance of this statement would be cute in a child,
deplorable in a thinking adult. If every reactor in the world were shut down
tomorrow, there wouldn't be enough power to light the lamp over your desk, let alone
run the computer you used to post this. The alternatives at this time are hundreds of
coal and oil fired generators, sulfur dioxide in your lungs, and massive global
warming. Do you have electric lights? Microwave oven? A vacuum cleaner? Power
tools? A refrigerator? No matter where in the world you live, much of the power that
runs these things for you comes from uranium. So stop contributing to the problem -
turn off your computer.

But this is comp.lang.c. Not alt.greenpeace. We digress.


J. Benz

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to

Lawrence Kirby wrote:

> >Seems pretty clear to me that goto was included in the language against the
> >better judgement of the authors, probably because most programmers of the day
> >felt naked without it. It also seems pretty clear that DMR and BWK didn't
> >consider goto a 'good thing' at all.
>

> You could also argue that K&R included this text to deflect criticism from
> the structured programming fanatics of the time (and there really were
> fanatics, much more so than now). Of course neither of these interpretations
> alone tells the whole story.

Right. The only ones who can tell the whole story are K&R themselves, and I
haven't seen a posting in c.l.c from either one of them for a long time now. And
I am definitely *not* a structured programming fanatic, and only responded to an
unsupported assertion that the inclusion of goto in the language was an
endorsement of its use by the authors, which doesn't appear to be the case. In my
own code I use whatever works best, and although it's been a long time since I
even considered using goto, that's probably more due to the fact that I work
mostly in business/DP apps, which are rarely complicated enough to generate the
special cases where goto is useful. We don't make any hard and fast rules here
about it, or any other point of C style or syntax, but a coder who uses a goto
around here better have a good reason handy at the code review.


Jens Schweikhardt

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
raw...@my-dejanews.com wrote:
# In article <72e6jh$d2f$2...@news.BelWue.DE>,
# Jens Schweikhardt <schw...@diamant.noc.dfn.de> dares to defy Stephan:

[tcp_input() without goto -- go for (to?) it]

#> Try to do this without goto (sure, it can be done on a theoretical basis).
#> But would you be sure your code does what the spec requires?

# Yes. Are you sure the goto code does what the spec requires?

A valid point. However, IMHO it's easier to verify the correctness
of the code that follows the spec "literally" than to verify
the code that looks different in more than one way.

Helmut Leitner

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
raw...@my-dejanews.com wrote:
>...

> state = STARTING_STATE;
> while (state != DONE_STATE)
> > switch (state) {
> >
> > case SYN-RECEIVED STATE:
> > case ESTABLISHED STATE:
> state = CLOSE_WAIT; /* goto CLOSE-WAIT state; */
> break;
> >
> > case FIN-WAIT-1 STATE:
> >
> > if (our FIN has been ACKed)
> state = TIME_WAIT; /* goto TIME-WAIT; */
> > else
> state = CLOSING; /* goto CLOSING; */
> break;
> > ...
> > }
>
> ...

> One advantage of the while-switch approach is that the set of states
> can be listed as an enumeration and thus documented in one place,
> and checked by the compiler (to the extent that C enumerations can
> be checked). Another advantage is that it keeps Stephan happy.

The while/switch may be beautiful but it has not a
good performance compared to the simple goto ....

Helmut

Douglas A. Gwyn

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
"J. Benz" wrote:
> The only ones who can tell the whole story are K&R themselves, ...

I can't tell exactly that story, but I've been in the C/UNIX community
for a *long* time now, and was the only non-Bell Labs prepublication
reviewer/proofreader of K&R2, so I have some insight into "goto" in C.
There are a handful of "goto"s in UNIX C code, and there would probably
be more if error recovery had been taken more seriously. That is the
main legitimate use for goto -- to get out of nested clauses when
normal processing cannot proceed due to some problem, without unduly
complicating the conditional control expressions. Proof of program
correctness is just about as hard no matter *how* one aborts processing
in the midst of such situations. (In BRL/ARL's MUVES project, we
adopted a very stylized form of error escape processing using gotos and
"erN:" labels; if we were to start over today, most of this would be
done using a new "exception handling" package that is analogous to the
C++ facility.)

Use of goto to implement ordinary looping constructs is definitely
considered bad practice (that has earned the epithet "spaghetti code").

"goto" is of course not the only way to "jump around" in C code;
other ways include setjmp/longjmp (which may have high overhead),
return from the middle of a function body, "break", and "Duff's
device". Experience shows that code reliability is higher and its
maintenance is easier if all such forms of jumping around are used
only sparingly and with good justification each time.

Mathew Hendry

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
Helmut Leitner <lei...@hls.via.at> wrote:

: raw...@my-dejanews.com wrote:
: > ...


: > One advantage of the while-switch approach is that the set of states
: > can be listed as an enumeration and thus documented in one place,
: > and checked by the compiler (to the extent that C enumerations can
: > be checked). Another advantage is that it keeps Stephan happy.
:
: The while/switch may be beautiful but it has not a
: good performance compared to the simple goto ....

That depends upon the compiler, of course. switch statements can often
be implemented using jump tables, and some compilers will perform this
optimisation for you, effectively providing a structured goto.

On the other hand, bare goto statements, particularly those which jump
backwards in the code, will confuse the hell out of the dataflow
analysis pass of most optimisers.

-- Mat.


raw...@my-dejanews.com

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <danpop.9...@news.cern.ch>,

Dan...@cern.ch (Dan Pop) wrote:
>
> >Steve Summit wrote:
> >
> >> On the other hand, if one cares about rigorous, formal
> >> specification, it can certainly be argued that every instance
> >> of behavior labeled as "undefined" represents a blemish (if not
> >> an outright defect) in a Standard.
>
> It's also what makes C so powerful and popular.

I guess I don't understand how undefined behavior instead of
implementation defined behavior makes C more powerful, or
more popular with programmers (implementors would obviously
not like the increased burden). (Well, OK, It's not clear from
either post whether implementation defined behavior is viewed
as well-defined or not; I'm assuming it is.)

> >> I've heard it claimed (by someone who was presumably in a better
> >> position to make such characterizations than I) that the "gulf of
> >> undefined behavior" is particularly wide in C, as opposed to
> >> other languages.
>
> And this is precisely why C is more popular than the other languages, with
> narrower "gulfs of undefined behavior". A wider gulf means a wider class
> of problems that can be solved in that language. Again, it's the choice
> between no solution at all and a non-portable solution.

OK, how does having void main produce nasal demons instead of
ending compilation with a diagnostic lead to being able to solve
more problems? There are very few areas of undefined behavior
in C that are needed for extensibility, and other languages with
narrower "gulfs of undefined behavior" manage to provide as
much extensibility.

Lawrence Kirby

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <364B18D9...@hls.via.at>
lei...@hls.via.at "Helmut Leitner" writes:

>raw...@my-dejanews.com wrote:
>>...
>> state = STARTING_STATE;
>> while (state != DONE_STATE)
>> > switch (state) {
>> >
>> > case SYN-RECEIVED STATE:
>> > case ESTABLISHED STATE:
>> state = CLOSE_WAIT; /* goto CLOSE-WAIT state; */
>> break;
>> >
>> > case FIN-WAIT-1 STATE:
>> >
>> > if (our FIN has been ACKed)
>> state = TIME_WAIT; /* goto TIME-WAIT; */
>> > else
>> state = CLOSING; /* goto CLOSING; */
>> break;
>> > ...
>> > }
>>

>> ...
>> One advantage of the while-switch approach is that the set of states
>> can be listed as an enumeration and thus documented in one place,
>> and checked by the compiler (to the extent that C enumerations can
>> be checked). Another advantage is that it keeps Stephan happy.
>
>The while/switch may be beautiful but it has not a
>good performance compared to the simple goto ....

However in this particular case it is not important since the state
changes so infrequently (i.e. taking a couple more clock cycles isn't going
to make any form of noticable or measurable difference). Also most
TCP/IP implementations have ways used by programs like netstat to query
the current state so it needs to be held separately anyway.

Lawrence Kirby

unread,
Nov 12, 1998, 3:00:00 AM11/12/98
to
In article <72es7b$tpo$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:

...

>One advantage of the while-switch approach is that the set of states
>can be listed as an enumeration and thus documented in one place,
>and checked by the compiler (to the extent that C enumerations can
>be checked). Another advantage is that it keeps Stephan happy.

Another advantage (and most of the state machines I've coded have made
use of this) is that the function containing the state machine can return
and then easily be reentered at the correct state.

Will Rose

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
Stephan Wilms (Stepha...@CWA.de) wrote:
[...]
: In the area where we work my banning aproach has worked out for some

: 6 years so far with not so much as a trace of a good use for goto (yet).
: Actually I am not really a tough hardliner at all. If someone explains
: to me a good reason for using a "goto", I will probably let it be. The
: problem is that (IMHO) free use of "goto" can do a lot of damage to
: the code. I have seen and written my own share of BASIC code

I can't recall ever using goto in 14-15 years of C programming; and
oddly enough, having used it heavily (and with extreme caution) in
an early Basic I really thought I was going to miss it. However,
there is certainly a use for it in exception and error handling; I
just don't handle errors that way (I use state variables instead).
This means convoluted code, at times; possibly as convoluted as
code using goto would be, but I personally prefer the style I use.


Will
c...@crash.cts.com


tst...@my-dejanews.com

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
In article <364AF3C9...@danet.com>,

"J. Benz" <be...@danet.com> wrote:
>
>
> tst...@my-dejanews.com wrote:
>
> > In article <3649CF3C...@danet.com>,
> > "J. Benz" <be...@danet.com> wrote:
> > >
> > >
> > >
> > > Seems pretty clear to me that goto was included in the language against
the
> > > better judgement of the authors, probably because most programmers of the
day
> > > felt naked without it. It also seems pretty clear that DMR and BWK
didn't
> > > consider goto a 'good thing' at all.
> > >
> > >
> >
> > But they *did* include it.
> >
> > The following contains heretical statements.
> >
> > K&R are not Gods, you do not have to take whatever they say as absolute
truth.
>
> This was not offered as a blood sacrifice either - willing virgins weren't
> available. Merely a refutation to your contention, that their inclusion of
goto in

> the language was any kind of endorsement of the wisdom of its use - what
better
> evidence than the author's own words? What *you* endorse is your own
problem.
> Yeah, they *did* include it, but apparently they *didn't* like it. As for
their

I wasn't suggesting that the inclusion was an endorsemeent for use of goto,
but a recognition that other people may find a use for it, their expression
of dislike being a strong reccomendation not to use it. In approxiamtely 8
years of C programming I have only ever used goto (singular) on 3 occasions.
I don't endorse rampant (or even normal) use of goto, but recognise that
(very) ocassionally it is useful, which is actually also stated in K&R, a
fact which was 'conveniently' left out of the post I was answering.

> motives, why don't you call up Bell Labs and see if you can get DMR on the
phone,
> and ask him? It could be as simple as having one extra slot in the token
table,
> and they couldn't figure out what else to put into the language.

Which would then make the whole language suspect :)

>
> But we've strayed a little from the technical... and into the realm of trying
to
> guess the intent of people who aren't party to the discussion. A singularly
futile
> thing to do.
>
>

My heretical statement was to highlight the illogic that often crops up when
people reason that a thing must be done a certain way becuase that's the way
it is done in K&R.

--
Tristan Styles

Failure is not an option
It is Standard Operating Procedure

-----------== Posted via Deja News, The Discussion Network ==----------

nick.k...@gecm.com

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
In article <364AFA47...@danet.com>,
"J. Benz" <be...@danet.com> wrote:

>
> Lawrence Kirby wrote:
>
> > >Seems pretty clear to me that goto was included in the language against the
> > >better judgement of the authors, probably because most programmers of the
> > >day felt naked without it. It also seems pretty clear that DMR and BWK
> > >didn't consider goto a 'good thing' at all.
> >
> > You could also argue that K&R included this text to deflect criticism from
> > the structured programming fanatics of the time (and there really were
> > fanatics, much more so than now). Of course neither of these interpretations
> > alone tells the whole story.
>
> Right. The only ones who can tell the whole story are K&R themselves, and I
> haven't seen a posting in c.l.c from either one of them for a long time now.

Dennis Richie posted recently after some idiot put a copy of K&R on the web
without permission.

> And I am definitely *not* a structured programming fanatic, and only responded

> to an unsupported assertion that the inclusion of goto in the language was an


> endorsement of its use by the authors, which doesn't appear to be the case.
> In my own code I use whatever works best, and although it's been a long time
> since I even considered using goto, that's probably more due to the fact that
> I work mostly in business/DP apps, which are rarely complicated enough to
> generate the special cases where goto is useful.

I work on telecommunication applications which are arguably (?) more
complicated than business apps. It is a long time since I used a goto. I
think I've only done it once in 7 years (I had to look it up) of C coding.

> We don't make any hard and
> fast rules here about it, or any other point of C style or syntax, but a coder
> who uses a goto around here better have a good reason handy at the code
> review.
>

sounds sensible

nick.k...@gecm.com

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
In article <3649D4...@soton.ac.uk>,

Adam Fordyce <n...@soton.ac.uk> wrote:
>
> As for your opinions regarding the goto statement, it looks to me like
> you have read K&R, heard lots of people (who have also read it) saying
> how bad "goto" is and have decided it *must* be a bad thing if all these
> people agree! It's easy to understand why. I mean, imagine the flaming
> someone would receive if he/she had the guts to write an article
> explaining how prevalent the word "goto" was in the latest release of
> their application.

application: telecommuncications
lines: 102,400
goto staements: 0

> You hear stories of "unmanageable, spaghetti code"
> but find that half the people who are so against poor old goto, have had
> *extremely* limited programming experience; certainly not enough to
> justify a valid opinion on the subject. Oh and before you reply telling
> me how many years you have been hacking, I'm talking generally, not
> specifically about your case ok?

ok. I've been programming for 19 years, 7 of them in C. Is this "*extremely*
limited programming experience"? If not then IMNSHO the excessive use of
'goto' is an extremly bad idea. It does lead to "spagetti" code which is hard
to understand, determine the correctness of, test and may even confuse the
compiler enough to preclude optimisation. Have you read "Go To Statement
Considered Harmful" by Dijkstra (a famous computer scientist)? He clearly and
succinctly explains why the goto statement leads to poor code. Have you ever
tried to do maintainance on a 'goto' heavy program?

>
> Besides, people use goto statements all the time. I mean, what are the
> "case:" statements of a switch statement if they aren't goto labels with
> local scope?

no not really. They may be implemented that way, but case statements are at a
higher level of abstraction than a naked goto. Besides these are forward
jumps, it's the backwards jumps and the consequent strange loops that lead to
true goto-madness.

> I've sometimes found goto useful when breaking from nested
> loops, haven't you?

that's an acceptable use of goto. I tend not to do this, I use break or return
(which I agree, arn't strictly structured but are less unpleasant than goto).
I've never found a need for continue.

> Oh yeah, and assembly language is absolutely
> chockablock with goto statements so they can't be all that bad *grin*.

I take it "*grin*" means you understand assembler is at a lower level of
abstraction and its relevance to high level language design is a little
tenuous (well the language described must be implementable). Note that some
studies have shown that development in assembler is an order of magnitude
slower than development in an HLL.

>
> Oh well, just my thoughts,
>

just mine.

J. Benz

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to

nick.k...@gecm.com wrote:

> > Right. The only ones who can tell the whole story are K&R themselves, and I
> > haven't seen a posting in c.l.c from either one of them for a long time now.
>
> Dennis Richie posted recently after some idiot put a copy of K&R on the web
> without permission.
>

I saw that - but I suspect it was a troll. Otherwise, his lawyers would have
advised him to keep his opinions out of the public eye and let due process handle
it. Hard to believe DMR would intentionally discuss an infringement suit on the net
while it is still pending. Any lawyer worth having would have gagged him and tied
him to a chair first. Especially unbelievable since he hasn't been seen here in
years - why would he open his mouth now on a matter that might prejudice his case?
Besides, 'd...@bell.labs.com' is just too obvious a handle for someone so well known
- he probably goes by '39...@aol.com' or something like that now, just to avoid
having his mail server pounded by 'fan mail'.


Billy Chambless

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
In article <364C61F7...@danet.com>, "J. Benz" <be...@danet.com> writes:

|> nick.k...@gecm.com wrote:

|> > Dennis Richie posted recently after some idiot put a copy of K&R on the web
|> > without permission.

|> I saw that - but I suspect it was a troll.

It wasn't.

|> Besides, 'd...@bell.labs.com' is just too obvious a handle for someone
|> so well known
|> - he probably goes by '39...@aol.com' or something like that now, just to avoid
|> having his mail server pounded by 'fan mail'.

Well... while an "obvious handle" makes him easier to find for unwelcome mail, it also makes him eaiser to find for welcome mail -- for instance, for whoever informed him about the online K&R.

PS: The rest of this message IS a troll.

Besides, a Unix God on AOL?

Puh-lease!

Dan Pop

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
In <72fotm$o7j$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:

>In article <danpop.9...@news.cern.ch>,
> Dan...@cern.ch (Dan Pop) wrote:
>>
>> >Steve Summit wrote:
>> >
>> >> On the other hand, if one cares about rigorous, formal
>> >> specification, it can certainly be argued that every instance
>> >> of behavior labeled as "undefined" represents a blemish (if not
>> >> an outright defect) in a Standard.
>>
>> It's also what makes C so powerful and popular.
>
>I guess I don't understand how undefined behavior instead of
>implementation defined behavior makes C more powerful, or
>more popular with programmers (implementors would obviously
>not like the increased burden). (Well, OK, It's not clear from
>either post whether implementation defined behavior is viewed
>as well-defined or not; I'm assuming it is.)

Nope, it isn't. Well-defined behaviour is that defined by the standard.

The standard can demand implementation-defined behaviour only for certain
situations. It is the fact that whatever has been left undefined by the
standard can be defined by the implementor that makes C so powerful and
popular: new functionality can be added to the libraries, new keywords to
the language (provided they are in the implementation namespace), the
most flexible/performant solutions for dealing with exceptions can be
adopted.

Undefined behaviour does not mean that the implementation is forbidden
to document it. If an implementation chooses to extend the range of
printf conversion specifiers or to add support for threads, it is very
likely that it will document this fact.

OTOH, how would you require an implementation to handle the sequence
points issues in a well defined way?

How should the compiler diagnose the following statement:

*p = (*q)++;

Would you like to see a diagnostic like: "Warning: this statement is
illegal if p and q point to overlapping objects" imposed by the language
definition?

How would you have arithmetic exceptions cause well defined behaviour
without crippling the performance of certain implementations?

>> >> I've heard it claimed (by someone who was presumably in a better
>> >> position to make such characterizations than I) that the "gulf of
>> >> undefined behavior" is particularly wide in C, as opposed to
>> >> other languages.
>>
>> And this is precisely why C is more popular than the other languages, with
>> narrower "gulfs of undefined behavior". A wider gulf means a wider class
>> of problems that can be solved in that language. Again, it's the choice
>> between no solution at all and a non-portable solution.
>
>OK, how does having void main produce nasal demons instead of
>ending compilation with a diagnostic lead to being able to solve
>more problems?

If void main does make sense on a certain implementation, why require that
implementation to reject it? Ditto for main defined with three arguments
instead of the standard two.

>There are very few areas of undefined behavior
>in C that are needed for extensibility, and other languages with
>narrower "gulfs of undefined behavior" manage to provide as
>much extensibility.

All extensibility must come from the undefined areas of the language.
The smaller this area is, the less opportunities for extension you have.
Try to extend Fortran or Pascal without breaking code which is fully
conformant to the respective language definition and without breaking the
implementation's conformance to the standard.

In C, once I put something like:

#include <unistd.h>

in my code, I can get the full functionality of POSIX (if supported by my
implementation) without breaking the implementation's conformance to
the ANSI standard, because this include directive causes undefined
behaviour.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

Ben Pfaff

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
bi...@cast.msstate.edu (Billy Chambless) writes:

Besides, a Unix God on AOL?

Puh-lease!

Yeah, how could anyone who knows anything about anything hang out on
AOL? Like specifically, no one who knows anything about C could
possibly post from AOL.
--
(supporter of the campaign for grumpiness where grumpiness is due in c.l.c)

Please: do not email me copies of your posts to comp.lang.c
do not ask me C questions via email; post them instead

Chris Torek

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
Just to play devil's advocate a bit:

In article <72had0$80$1...@nnrp1.dejanews.com> <nick.k...@gecm.com> wrote:
>application: telecommuncications
>lines: 102,400
>goto staements: 0

application: system configuration generator
lines (wc -l): 5550
goto statements: 44 (about 0.8%)

Now, I would not claim this is my best code ever or anything. :-)

The actual "goto"s themselves are:

20 goto bad
2 goto badname
2 goto copy
1 goto foundstar
1 goto nextalias
1 goto ok
1 goto usage
13 goto wrerror
3 goto writeit

which means that most of them are involved in error recovery.

There are eight non-error-recovery "goto"s: "copy" (2), "foundstar",
"nextalias", "ok", and "writeit" (3).

The two "goto copy"s are in the ugliest section of the code, and
are hard to justify in any way. :-) The "goto writeit"s are in a
section of code that decides whether to write a new copy of a header
file (it is important not to change the time stamp on the existing
header, if the existing header is still valid). Because there is
also a possibility of an error reading an existing header, removing
them would be a bit messy (see below).

The "goto nextalias" is a really a two-level break, which could be
eliminated by repeating the inner loop test in the outer loop.
The "foundstar" is because a search loop is inside another loop:

for (d = allbases; d != NULL; d = d->d_next) {
for (i = d->d_ihead; i != NULL; i = i->i_bsame)
if (i->i_unit == STAR)
goto foundstar;
continue;
foundstar:
/* code to deal with "*" replicators */
}

which could legitimately be replaced with, e.g.:

for (d = allbases; d != NULL; d = d->d_next) {
if (!has_star(d->d_ihead))
continue;
/* code to deal with "*" replicators */
}

or (still in line, but now duplicating a test):

for (d = allbases; d != NULL; d = d->d_next) {
for (i = d->d_ihead; i != NULL; i = i->i_bsame)
if (i->i_unit == STAR)
break;
if (i == NULL)
continue;
/* code to deal with "*" replicators */
}

(and of course the "continue" can be eliminated by putting the main
body of the code inside {} and inverting the test).

The one "goto ok" breaks out of a (non-nested) loop and is
just to avoid duplicating a test:

...
for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
attr = nv->nv_ptr;
if (onlist(attr->a_devs, ib))
goto ok;
}
attr = &errattr;/* now onlist below will fail */
}
if (!onlist(attr->a_devs, ib)) {
error("%s's cannot attach to %s's", ib->d_name, atbuf);
goto bad;
}
}
ok:
...

This could be rewritten as:

...
for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
attr = nv->nv_ptr;
if (onlist(attr->a_devs, ib))
break;
}
if (nv == NULL)
attr = &errattr;/* now onlist below will fail */
}
if (!onlist(attr->a_devs, ib)) {
error("%s's cannot attach to %s's", ib->d_name, atbuf);
goto bad;
}
}

The code at this particular "bad" frees a list and returns. The
list is always freed, so all of these goto's could be removed by
replacing the function -- instead of:

void f(struct nvlist *list, etc, et, cetera) {
...
/* several occurrences of */ goto bad;
...
bad:
nvfreel(list);
}

we would have:

void f(struct nvlist *list, etc, et, cetera) {
f0(list, etc, et, cetera);
nvfreel(list);
}

void f0(struct nvlist *list, etc, et, cetera) {
...
/* replace all "goto bad"s with "return"s */
...
}

Similar arguments hold for the other "bad" and "wrerror" cases,
and the two "writeit" cases: most of the code could be moved down
into another function, and the inner function could return a failure
indicator (as well as any existing return value). But in this
case, I think the result is at best a wash. It replaces things
like:

some_type outer(args) {
...
if (horrible)
goto very_bad;
...
if (!good)
goto bad;
...
return some_value; /* and do NOT clean up */
very_bad:
clean_up_x();
/* and fall through to */
bad:
clean_up_y_and_z();
return another_value;
}

with:

some_type outer(args) {
int how_to_clean_up;
some_type return_val;

return_val = inner(args, &how_to_clean_up);
switch (how_to_clean_up) {
case ALL:
clean_up_x();
/* FALLTHROUGH */
case LOTS:
clean_up_y_and_z();
break;
case NONE:
break;
default:
panic("bad how_to_clean_up");
}
return return_val;
}

some_type inner(args, int *cleanup) {
...
if (horrible) {
*cleanp = ALL;
return another_value;
}
...
if (!good) {
*cleanp = SOME;
return another_value;
}
...
*cleanp = NONE;
return some_value;
}

Some would call this an improvement; as I said, I consider it
mostly a wash. Depending on the details, one form might wind
up cleaner than the other, but as a general rule I have no real
preference.

Incidentally, if one counts just the 8 non-error-recovery gotos,
the "goto fraction" drops to under 0.15% of the code. Three of
those eight could be eliminated fairly easily, as described above,
which would drop the goto ratio to just under 0.10%.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA Domain: to...@bsdi.com +1 510 234 3167
Antispam notice: unsolicited commercial email will be handled at my
consulting rate; pyramid-scheme mail will be forwarded to the FTC.

Ben Pfaff

unread,
Nov 13, 1998, 3:00:00 AM11/13/98
to
to...@elf.bsdi.com (Chris Torek) writes:

Just to play devil's advocate a bit:

In article <72had0$80$1...@nnrp1.dejanews.com> <nick.k...@gecm.com> wrote:
>application: telecommuncications
>lines: 102,400
>goto staements: 0

application: system configuration generator
lines (wc -l): 5550
goto statements: 44 (about 0.8%)

I was about to post something about how I don't use goto's very much
at all, but then I ran a similar grep on my biggest program and found
out the following:

application: statistical analysis software
lines: 66536
goto statements: 454 (about 0.7%)

However, I can defend most of these on the basis that they're error
recovery (the equivalent of C++'s try/catch constructs) or
multiple-break instructions:

1 goto H4;
1 goto H6;
2 goto H8;
3 goto INTO_fail;
1 goto again;
1 goto any_done;
1 goto any_string_done;
3 goto arabic;
1 goto break_out_of_loop;
1 goto breakout;
1 goto cache_miss;
1 goto case0;
11 goto done;
1 goto entry;
4 goto eof;
11 goto error;
1 goto escape;
9 goto exit;
103 goto fail;
2 goto fallback;
7 goto file_lossage;
4 goto finish;
1 goto finished;
4 goto found;
1 goto free;
1 goto gen_random;
2 goto got_ligature;
1 goto iterate;
20 goto lose;
184 goto lossage;
8 goto main_loop;
4 goto multiply;
1 goto next_case;
2 goto next_crosstab;
1 goto next_item;
3 goto next_iteration;
2 goto noconv;
4 goto not_equal;
4 goto overflow;
1 goto range_done;
1 goto range_str_done;
2 goto scientific;
1 goto skip_missing_values;
1 goto skip_value_labels;
1 goto start;
2 goto syntax_error;
2 goto underflow;
2 goto unexpected_eof;
4 goto win;
6 goto winnage;

(FWIW I used the command
grep -h goto *.[qch] | sed -e 's/^[ ]*\([^ ]\)/\1/;'|grep '^goto '|grep ';$'|sort|uniq -c
to generate this list.)

In fact, at first glance, I see only one function that can't easily be
excused in this manner, as follows:

/* Deletes the first element in the heap and returns its index, or -1
if the heap is empty. */
int
heap_delete (heap **hp, int *key)
{
/* Knuth's Algorithm 5.2.3H-19. */
heap *h = *hp;
int first, K, R, l, r, i, j;

if (h->n_elem == 0)
return -1;
first = h->elem[0].index;
if (key)
*key = h->elem[0].key;
K = h->elem[h->n_elem - 1].key;
R = h->elem[h->n_elem - 1].index;
l = 1;
r = h->n_elem - 1;

/* H3. */
j = 1;

H4:
i = j;
j *= 2;
if (j == r)
goto H6;
else if (j > r)
goto H8;

/* H5. */
if (h->elem[j - 1].key > h->elem[j].key)
j++;

H6:
if (K <= h->elem[j - 1].key)
goto H8;

/* H7. */
h->elem[i - 1] = h->elem[j - 1];
goto H4;

H8:
h->elem[i - 1].key = K;
h->elem[i - 1].index = R;

h->n_elem--;
return first;
}

My excuse for this hunk of spaghetti is that that's the way that Knuth
wrote it, and I wanted it to resemble his algorithm as closely as
possible so that I could be most assured that it was correct.
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz

raw...@my-dejanews.com

unread,
Nov 14, 1998, 3:00:00 AM11/14/98
to
In article <364AF778...@danet.com>,
"J. Benz" <be...@danet.com> wrote:

>
>
> William Roeder wrote:
> > IMNSHO a nuclear reactor is an error.
>
> IMNSHO, the naivete and ignorance of this statement would be cute in a child,
> deplorable in a thinking adult. If every reactor in the world were shut down
> tomorrow, there wouldn't be enough power to light the lamp over your desk, let alone
> run the computer you used to post this.

Nothing like hard numbers and unemotional statements to refute ideas you
don't like! You could execute the code that started this thread and (if
you're lucky/unlucky enough) discuss nuclear power with one occasionally
threatened result of undefined behavior, as long as you promise not to
bring him back here from sci.environment.

--
MJSR

Sunil Rao

unread,
Nov 14, 1998, 3:00:00 AM11/14/98
to
Ben Pfaff wrote:
>
> bi...@cast.msstate.edu (Billy Chambless) writes:
>
> Besides, a Unix God on AOL?
>
> Puh-lease!
>
> Yeah, how could anyone who knows anything about anything hang out on
> AOL? Like specifically, no one who knows anything about C could
> possibly post from AOL.

stuffed shirts! :)


--
{ Sunil Rao }
"And India acquired yet another willing convert to the philosophy of
the meaningfully meaningless... Or was it the meaninglessly
meaningful? Did anyone know what was happening?" -- Gita Mehta

Lawrence Kirby

unread,
Nov 14, 1998, 3:00:00 AM11/14/98
to
In article <72had0$80$1...@nnrp1.dejanews.com> nick.k...@gecm.com writes:

>In article <3649D4...@soton.ac.uk>,
> Adam Fordyce <n...@soton.ac.uk> wrote:
>>
>> As for your opinions regarding the goto statement, it looks to me like
>> you have read K&R, heard lots of people (who have also read it) saying
>> how bad "goto" is and have decided it *must* be a bad thing if all these
>> people agree! It's easy to understand why. I mean, imagine the flaming
>> someone would receive if he/she had the guts to write an article
>> explaining how prevalent the word "goto" was in the latest release of
>> their application.
>

>application: telecommuncications
>lines: 102,400
>goto staements: 0

There's no doubt that if you don't want to use gotos then you can avoid them
without too much trouble. Are you sure, however, that in those 102,400
lines of code that there is no siutation that couldn't arguably have been
better (more simply, clearly) implemented using goto?

A quick check here of a set of source files I've written gives 95 uses
of goto in 103362 lines. That's not a high rate but I suspect it is more than,
say the number of recursive function calls in the same code and uses of
function pointers (although I'm not sure about that). SO it may be enough to
justify the inclusion of goto in the language.

I guess an interesting question might be to what extent a more "structures"
constructs (e.g. multilevel break) could naturally replace the usage of goto.

>ok. I've been programming for 19 years, 7 of them in C. Is this "*extremely*
>limited programming experience"? If not then IMNSHO the excessive use of
>'goto' is an extremly bad idea. It does lead to "spagetti" code which is hard
>to understand, determine the correctness of, test and may even confuse the
>compiler enough to preclude optimisation. Have you read "Go To Statement
>Considered Harmful" by Dijkstra (a famous computer scientist)? He clearly and
>succinctly explains why the goto statement leads to poor code. Have you ever
>tried to do maintainance on a 'goto' heavy program?

I don't thing that there is any argument about excessive use of goto. What's
more interesting are justified uses of goto. That depends a great deal
on the programming language you are using. For example there is a great
deal more justified use of goto in Fortran-77 than in ANSI C but that doesn't
mean that there isn't any in ANSI C. The problem is that "justified use" is
always going to be subjective. One of the points that Fortran-77 brings
up is that you can write perfectly good structured code using goto. It
is undisciplined use that is a problem.

>> Oh yeah, and assembly language is absolutely
>> chockablock with goto statements so they can't be all that bad *grin*.
>
>I take it "*grin*" means you understand assembler is at a lower level of
>abstraction and its relevance to high level language design is a little
>tenuous (well the language described must be implementable). Note that some
>studies have shown that development in assembler is an order of magnitude
>slower than development in an HLL.

Productive assembly language programming requires a great deal of
discipline. Structured programming principles can be applied there too,
although it is more difficult.

Adam Fordyce

unread,
Nov 14, 1998, 3:00:00 AM11/14/98
to
> In article <72had0$80$1...@nnrp1.dejanews.com> nick.k...@gecm.com writes:
>
> >In article <3649D4...@soton.ac.uk>,
> > Adam Fordyce <n...@soton.ac.uk> wrote:
> >>
> >> As for your opinions regarding the goto statement, it looks to me like
> >> you have read K&R, heard lots of people (who have also read it) saying
> >> how bad "goto" is and have decided it *must* be a bad thing if all these
> >> people agree!

> >application: telecommuncications


> >lines: 102,400
> >goto staements: 0

What's your point here? I certainly didn't say substantial programs are
impossible to write without goto, did I?

>
> >ok. I've been programming for 19 years, 7 of them in C. Is this "*extremely*
> >limited programming experience"? If not then IMNSHO the excessive use of
> >'goto' is an extremly bad idea. It does lead to "spagetti" code which is hard
> >to understand, determine the correctness of, test and may even confuse the
> >compiler enough to preclude optimisation.

I'm positive I said in my original post that I wasn't specifically
referring to your case, and asking you not to write in explaining how
long you have been writing code. Ok, it certainly looks like good
credentials to formulate an opinion, but your opinion seems to be one of
common sense. *Excessive* drinking of water is an extremely bad idea,
but I wouldn't suggest removing it from your diet. IMO, small jumps
within the same scope do not make code unimaginably hard to read or
maintain especially if it's well commented. Large jumps of hundreds of
lines should be avoided, of course, but this wasn't the point I was
making.

> >I take it "*grin*" means you understand assembler is at a lower level of
> >abstraction and its relevance to high level language design is a little
> >tenuous (well the language described must be implementable).

Although my programming experience in assembler is rather limited, I do
recognise the huge difference in the relative levels of abstraction.
Have no fear; it was indeed a light hearted comment.

So to wrap it all up, I don't think goto is the answer to all our
programming need, by any stretch of the imagination. I agree, code can
be written without a single one. I do not think, however, that banning
something just because excessive use of it is a bad thing should be
condoned. As coders, we do what we need to do, to get the job done in
the best way. Banning the use of a tool which may have legitimate,
albeit small, uses seems to be a bit silly.

Adam

Peter Shaggy Haywood

unread,
Nov 16, 1998, 3:00:00 AM11/16/98
to
Groovy hepcat Alex Lemelev was jivin' on 5 Nov 1998 14:42:35 +0200 in
comp.lang.c.
Interesting question in C's a cool scene! Dig it!

>What is the output of the following C program ?
>
>void main()
>{
> int i , j = 3;
>
> i = ++j * ++j;
> printf("%d\n", i);
>}

What is the sound of one hand clapping? If a tree falls, and nobody
is there to hear, does it make a sound? Is a bear catholic? Does the
pope shit in the woods?
--

----- Dig the EVEN NEWER, MORE IMPROVED news sig!! -----

-------------- Shaggy was here! ---------------
http://aardvark.apana.org.au/~phaywood/
============= Ain't I'm a dawg!! ==============


Peter Shaggy Haywood

unread,
Nov 16, 1998, 3:00:00 AM11/16/98
to
Groovy hepcat Will Rose was jivin' on 5 Nov 1998 19:38:12 GMT in
comp.lang.c.
Re: Interesting question in C's a cool scene! Dig it!

>: void main()


>: {
>: int i , j = 3;
>:
>: i = ++j * ++j;
>: printf("%d\n", i);

>: }
>end of main(). However, the line 'int i, j = 3' seems correct:

There are three other correct lines in that program. They are the
second, the fourth, and seventh lines. :)

raw...@my-dejanews.com

unread,
Nov 16, 1998, 3:00:00 AM11/16/98
to
In article <danpop.9...@news.cern.ch>,
Dan...@cern.ch (Dan Pop) wrote:
> In <72fotm$o7j$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:
>
> >In article <danpop.9...@news.cern.ch>,
> > Dan...@cern.ch (Dan Pop) wrote:
> >>
> >> >Steve Summit wrote:
> >> >
> >> >> On the other hand, if one cares about rigorous, formal
> >> >> specification, it can certainly be argued that every instance
> >> >> of behavior labeled as "undefined" represents a blemish (if not
> >> >> an outright defect) in a Standard.
> >>
> >> It's also what makes C so powerful and popular.
> >
> >I guess I don't understand how undefined behavior instead of
> >implementation defined behavior makes C more powerful, or
> >more popular with programmers (implementors would obviously
> >not like the increased burden). (Well, OK, It's not clear from
> >either post whether implementation defined behavior is viewed
> >as well-defined or not; I'm assuming it is.)
>
> Nope, it isn't. Well-defined behaviour is that defined by the standard.

Steve Summit's post divided program fragments into well-defined,
undefined and illegal. It wasn't clear where to put implementation
defined behavior; I would prefer to have a fourth category, and
would not view instances falling into that category as blemishes
on the standard, even though I care about rigorous, formal specification.

Trying to detect all errors would eventually require some run-time
checking and thus hurt performance. "Well-defined" as you describe
it would be bad, since it would restrict possible implementations.
What I'm looking for is some way to bound the risk of running
possibly bad code; it's hard luck to have all your files deleted every
time you code an off-by-one error when accessing an array, and
I'd like the implementation to warn me of how nasty it might get with
various undefined behavior.

> OTOH, how would you require an implementation to handle the sequence
> points issues in a well defined way?
>
> How should the compiler diagnose the following statement:
>
> *p = (*q)++;
>
> Would you like to see a diagnostic like: "Warning: this statement is
> illegal if p and q point to overlapping objects" imposed by the language
> definition?

No, no need for a diagnostic. I would like the standard to say that
an implementation must specify one of two choices with regard to
sequence point issues:
1) some arbitrary order consistent with the present requirements is
chosen; the result of, say, x = x++ is whatever that order produces.
2) through some special mechanism, correct values of correct
expressions are computed; incorrect expressions (like above, if
p and q point to overlapping objects) may cause files to be deleted,
the computer to explode or more disastrous results.

Wouldn't most implementations fall into the first group?
The second choice would occur only if the compiler was
written by smartasses or if the most efficient use of the hardware
necessitated assuming correct expressions (possibly true for
dataflow machines, machines that overlap operations, etc);
either way, the programmer should be warned of the danger
and its extent. (This wouldn't affect power, since the
implementation would be identical except in documentation;
it shouldn't affect popularity much, since most programmers
don't read the documentation.)

> >There are very few areas of undefined behavior
> >in C that are needed for extensibility, and other languages with
> >narrower "gulfs of undefined behavior" manage to provide as
> >much extensibility.
>
> All extensibility must come from the undefined areas of the language.
> The smaller this area is, the less opportunities for extension you have.
> Try to extend Fortran or Pascal without breaking code which is fully
> conformant to the respective language definition and without breaking the
> implementation's conformance to the standard.

This is wrong. Extending Pascal is very easy, since the syntax is
fairly restrictive (verbose, in the opinion of most C programmers).
For example, a standard Pascal program must start with the
reserved word program, so any extension that is indicated by
starting with a different token would not break correct programs, e.g.,
extension 'POSIX';
program main(input,output); (* etc. *)
It should be noted that the correct way to add POSIX functions
would be to use an implementation specific directive like
function SomePOSIXFunction(arg1 : integer) : integer; external;
External is very common for this purpose, and (if documented)
does not break compliance with ISO 7185:1990. (A compliant
implementation can do a lot of stuff IF it documents the extensions,
so compliance with the standard is not a problem.) Externally
defined types can be added in several ways with no risk of
breaking conforming programs.

The disadvantage of extending some vaguely plausible code that
an implementation may not be able to reject without a run-time
check (like fflush(stdin)) is that code using that extension will
compile on unextended implementations, possibly with no
warnings and with disastrous consequences.

V. Raghavendra Holla.

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
25 is o/p, Ha Ha Ha ......!!!
--
V. Raghavendra Holla.
Raghaven...@bosch.com

Undistroyable Nation " INDIA ".


Peter "Shaggy" Haywood <phay...@aardvark.apana.org.au.STOP.SPAM> wrote in
article <3647a699...@news.aardvark.apana.org.au>...


| Groovy hepcat Alex Lemelev was jivin' on 5 Nov 1998 14:42:35 +0200 in
| comp.lang.c.

| Interesting question in C's a cool scene! Dig it!
|

| >What is the output of the following C program ?
| >

| >void main()
| >{
| > int i , j = 3;
| >
| > i = ++j * ++j;
| > printf("%d\n", i);
| >}
|

| What is the sound of one hand clapping? If a tree falls, and nobody
| is there to hear, does it make a sound? Is a bear catholic? Does the
| pope shit in the woods?

Dan Pop

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
In <72pp61$q7b$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:

>In article <danpop.9...@news.cern.ch>,
> Dan...@cern.ch (Dan Pop) wrote:
>>
>> How should the compiler diagnose the following statement:
>>
>> *p = (*q)++;
>>
>> Would you like to see a diagnostic like: "Warning: this statement is
>> illegal if p and q point to overlapping objects" imposed by the language
>> definition?
>
>No, no need for a diagnostic. I would like the standard to say that
>an implementation must specify one of two choices with regard to
>sequence point issues:
>1) some arbitrary order consistent with the present requirements is
>chosen; the result of, say, x = x++ is whatever that order produces.
>2) through some special mechanism, correct values of correct
>expressions are computed; incorrect expressions (like above, if
>p and q point to overlapping objects) may cause files to be deleted,
>the computer to explode or more disastrous results.

The current standard is making the second choice the default, while
allowing an implementation to adopt the first choice. So, as far as I
can tell, you already have what you want.

>> Try to extend Fortran or Pascal without breaking code which is fully
>> conformant to the respective language definition and without breaking the
>> implementation's conformance to the standard.
>
>This is wrong. Extending Pascal is very easy, since the syntax is
>fairly restrictive (verbose, in the opinion of most C programmers).
>For example, a standard Pascal program must start with the
>reserved word program, so any extension that is indicated by
>starting with a different token would not break correct programs, e.g.,
> extension 'POSIX';
> program main(input,output); (* etc. *)

Isn't any conforming Pascal implementation required to diagnose the
"extension 'POSIX';" statement as a syntax violation?

Or is this "extension" thing a legal feature of the language, a la the
C #pragma?

raw...@my-dejanews.com

unread,
Nov 17, 1998, 3:00:00 AM11/17/98
to
In article <danpop.9...@news.cern.ch>,
Dan...@cern.ch (Dan Pop) wrote:
> In <72pp61$q7b$1...@nnrp1.dejanews.com> raw...@my-dejanews.com writes:
> >Extending Pascal is very easy, since the syntax is
> >fairly restrictive (verbose, in the opinion of most C programmers).
> >For example, a standard Pascal program must start with the
> >reserved word program, so any extension that is indicated by
> >starting with a different token would not break correct programs, e.g.,
> > extension 'POSIX';
> > program main(input,output); (* etc. *)
>
> Isn't any conforming Pascal implementation required to diagnose the
> "extension 'POSIX';" statement as a syntax violation?

An implementation does not sacrifice compliance if it is "accompanied
by a document that separately describes any features accepted
by the processor that are prohibited or not specified" in the standard;
such extensions are also required not to break conforming programs,
except by prohibiting the use of one or more spellings of identifiers
(i.e., extending the list of reserved words). In the example above,
it would not even be necessary to make extension a reserved word
if its only special use is prior to the reserved word program.

An implementation is required to reject extensions it does not support
if they are based on such syntax violations. There is of course the
danger that two implementations might have different meanings
for the same extension, which certainly argues against non-verbose
extensions (e.g., {$P+} to enable POSIX extensions).

It is peculiar to me that on the one hand, the C standard allows an
implementation to lay literally fatal traps around undefined behavior
and that on the other hand, so many C programmers take such a
lax attitude toward the correctness of their code. I would still be
happier if the standard required implementations to describe explicitly
how mean they might be with undefined behavior; if nothing else,
this would at least give some incentive for reducing their meanness.

0 new messages