Undefined?

2 views
Skip to first unread message

Tak-Shing Chan

unread,
Nov 5, 2002, 1:30:33 PM11/5/02
to
On 5 Nov 2002, Dan Pop wrote:

> It is not clear (to me, at least), whether the standard makes a
> distinction between translation-time undefined behaviour and execution-time
> undefined behaviour.

It is clear (to everyone else) that the standard only cares
about execution-time undefined behaviour. Here is a strictly
conforming program:

int main(void) { return 0 && (1 / 0); }

[Crossposted to comp.std.c. Corrections are welcomed.]

Tak-Shing

Blah

unread,
Nov 5, 2002, 1:40:22 PM11/5/02
to
*** post for FREE via your newsreader at post.newsfeed.com ***

Actually, it was NOT clear to me, which is why I asked in the first
place.


-----= Posted via Newsfeed.Com, Uncensored Usenet News =-----
http://www.newsfeed.com - The #1 Newsgroup Service in the World!
-----== 100,000 Groups! - 19 Servers! - Unlimited Download! =-----

Jun Woong

unread,
Nov 5, 2002, 2:18:30 PM11/5/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0211051820230.5385-100000@swindon...

> On 5 Nov 2002, Dan Pop wrote:
>
> > It is not clear (to me, at least), whether the standard makes a
> > distinction between translation-time undefined behaviour and
execution-time
> > undefined behaviour.
>
> It is clear (to everyone else) that the standard only cares
> about execution-time undefined behaviour.

Dan is right. There is no distinction between translation-time UB and
execution-time UB.

> Here is a strictly
> conforming program:
>
> int main(void) { return 0 && (1 / 0); }
>

Yes, this is a s. c. program. IIRC, the Standard requires an
implementation not to fail to translate and to execute a program
unless every possible execution of the program results in undefined
behavior; if every possible execution of a program results in
undefined behavior, then an implementation is allowed to fail to
translate it.

Thanks.


--
Jun, Woong (myco...@hanmail.net)
Dept. of Physics, Univ. of Seoul

Martin Dickopp

unread,
Nov 5, 2002, 2:55:22 PM11/5/02
to
In comp.lang.c Tak-Shing Chan <es...@city.ac.uk> wrote:
> It is clear (to everyone else) that the standard only cares about
> execution-time undefined behaviour.

It is not clear to me. Section 3.4.3 defines undefined behavior in the
following way:

| 1 undefined behavior
| behavior, upon use of a nonportable or erroneous program construct
| or of erroneous data, for which this International Standard
| imposes no requirements
|
| 2 NOTE Possible undefined behavior ranges from ignoring the
| situation completely with unpredictable results, to behaving
| during translation or program execution in a documented manner
| characteristic of the environment (with or without the issuance of
| a diagnostic message), to terminating a translation or execution
| (with the issuance of a diagnostic message).

I understand the phrase "imposes no requirements" to mean that no
requirements are imposed on either the translation or the execution-
time behavior. The note, although not normative, seems to indicate
that this is in fact the intended meaning.

Martin

Martin Dickopp

unread,
Nov 5, 2002, 3:07:41 PM11/5/02
to
In comp.lang.c Jun Woong <myco...@hanmail.net> wrote:
> "Tak-Shing Chan" <es...@city.ac.uk> wrote in message
> news:Pine.GSO.4.21.0211051820230.5385-100000@swindon...
>> It is clear (to everyone else) that the standard only cares
>> about execution-time undefined behaviour.
>
> Dan is right. There is no distinction between translation-time UB and
> execution-time UB.
>
>> Here is a strictly conforming program:
>>
>> int main(void) { return 0 && (1 / 0); }
>
> Yes, this is a s. c. program.

Now I'm completely confused. If you agree that there is no distinction
between translation-time and execution-time undefined behavior, how
can this program be strictly conforming?

> IIRC, the Standard requires an implementation not to fail to
> translate and to execute a program unless every possible execution
> of the program results in undefined behavior; if every possible
> execution of a program results in undefined behavior, then an
> implementation is allowed to fail to translate it.

Which section of the standard says so?

Martin

Tak-Shing Chan

unread,
Nov 5, 2002, 3:31:41 PM11/5/02
to
On Tue, 5 Nov 2002, Martin Dickopp wrote:

> In comp.lang.c Tak-Shing Chan <es...@city.ac.uk> wrote:
>> It is clear (to everyone else) that the standard only cares about
>> execution-time undefined behaviour.
>
> It is not clear to me. Section 3.4.3 defines undefined behavior in the
> following way:
>
> | 1 undefined behavior
> | behavior, upon use of a nonportable or erroneous program construct
> | or of erroneous data, for which this International Standard
> | imposes no requirements

If the program construct or data is not in the execution
path, how can it ever be used?

Tak-Shing

Martin Dickopp

unread,
Nov 5, 2002, 3:54:04 PM11/5/02
to

It is used by the programmer. S/he uses a nonportable or erroneous
construct and feeds it to the compiler.

This section defines the term "undefined behavior"; it does not define
under what circumstances some behavior is undefined. The latter is
defined in 4 (2).

Martin

Tak-Shing Chan

unread,
Nov 5, 2002, 4:18:50 PM11/5/02
to
On Tue, 5 Nov 2002, Martin Dickopp wrote:

> In comp.lang.c Tak-Shing Chan <es...@city.ac.uk> wrote:
>> If the program construct or data is not in the execution path,
>> how can it ever be used?
>
> It is used by the programmer. S/he uses a nonportable or erroneous
> construct and feeds it to the compiler.

I believe that ``used by the programmer'' is outside the
scope of the standard.

Tak-Shing

E. Gibbons

unread,
Nov 5, 2002, 5:19:34 PM11/5/02
to
In article <Pine.GSO.4.21.0211052021500.10697-100000@swindon>,

This, taken in isolation, sounds to me like it refers to "use" in the
sense of using a construct when *writing* a program. I'd expect some
other word or phrasing to be used, like "upon execution", if that's
what was meant.

After all, programs can "use" macros, #define statements, symbolic
constants, FILE pointers, etc., right? But arguably, these things
no longer exist as such, by the time of *execution*.

#include "somefile.h"

void f(int n)
{
if(n)
do_something();
else
do_something_else();
}

int main(void)
{
f(1);
return 0;
return 1; /*NOTREACHED*/
}

The function f() above, as called from main(), clearly seems to "use" the
if statement. But does it "use" the else? It would certainly have a
different meaning if the else were not there! I would say this program
"uses" if and else. Does it "use" an #include directive? Does it "use"
somefile.h? It "uses" a "/*NOTREACHED*/" comment, does it not? But
surely you'll agree that *that* isn't *executed*!

--Ben

--

Tak-Shing Chan

unread,
Nov 5, 2002, 5:44:17 PM11/5/02
to

According to the as-if rule, your program is equivalent to:

#include "somefile.h"
int main(void) { do_something(); return 0; }

So no, I don't think the ``else'' part is used.

Tak-Shing

E. Gibbons

unread,
Nov 5, 2002, 6:02:23 PM11/5/02
to
In article <Pine.GSO.4.21.0211052241270.14654-100000@swindon>,

Perhaps you're right; I went through all that with defining an
additional function, specifically to guard against the notion that
parts of the program might be optimized out of existence (since I
wanted to use a constant in the test). Perhaps a judiciously-placed
"extern" could help? Or how about this:

#include <stdio.h>

int main(void)
{
f(getchar()=='y');


return 0;
return 1; /*NOTREACHED*/
}

(And the rest same as above.)

All my points above still hold for this modified program, and I hope this
lays to rest your "as-if" diversion. Of course, in *my* interpretation,
"as-if" doesn't matter because "use" refers to constructs that are "used"
in the *source code* of the program, prior to compilation, execution, or
any applicability of "as-if". Anyway, please address my points in light
of this new program.

--Ben

--

Tak-Shing Chan

unread,
Nov 5, 2002, 6:39:43 PM11/5/02
to
On 5 Nov 2002, E. Gibbons wrote:

> In article <Pine.GSO.4.21.0211052241270.14654-100000@swindon>,
> Tak-Shing Chan <es...@city.ac.uk> wrote:
>> So no, I don't think the ``else'' part is used.
>
> Perhaps you're right; I went through all that with defining an
> additional function, specifically to guard against the notion that
> parts of the program might be optimized out of existence (since I
> wanted to use a constant in the test). Perhaps a judiciously-placed
> "extern" could help? Or how about this:
>
> #include <stdio.h>
>
> int main(void)
> {
> f(getchar()=='y');
> return 0;
> return 1; /*NOTREACHED*/
> }
>
> (And the rest same as above.)

You now have two distinct execution paths for this program:
one ``uses'' the if part while the other ``uses'' the else part.

> All my points above still hold for this modified program, and I hope this
> lays to rest your "as-if" diversion. Of course, in *my* interpretation,
> "as-if" doesn't matter because "use" refers to constructs that are "used"
> in the *source code* of the program, prior to compilation, execution, or
> any applicability of "as-if". Anyway, please address my points in light
> of this new program.

If this were true, then you should be able to state whether
the following program invokes undefined behavior or not (prior to
compilation or execution):

#include <stdio.h>
int main() { char s[9]; gets(s); puts(s); }

Can you do this?

Tak-Shing

Jun Woong

unread,
Nov 5, 2002, 6:40:21 PM11/5/02
to
"Martin Dickopp" <firefl...@gmx.net> wrote in message
news:aq98ed$h7r$03$1...@news.t-online.com...

> In comp.lang.c Jun Woong <myco...@hanmail.net> wrote:
> > "Tak-Shing Chan" <es...@city.ac.uk> wrote in message
> > news:Pine.GSO.4.21.0211051820230.5385-100000@swindon...
> >> It is clear (to everyone else) that the standard only cares
> >> about execution-time undefined behaviour.
> >
> > Dan is right. There is no distinction between translation-time UB and
> > execution-time UB.
> >
> >> Here is a strictly conforming program:
> >>
> >> int main(void) { return 0 && (1 / 0); }
> >
> > Yes, this is a s. c. program.
>
> Now I'm completely confused. If you agree that there is no distinction
> between translation-time and execution-time undefined behavior, how
> can this program be strictly conforming?

There seems to be misunderstanding. I said there is no distinction
in the sense of that the criterion is when the visible effect of the
undefined behavior can occur.

int main(void)
{
return 1/0;
}

The every possible execution of this program results in undefined
behavior, so the implementation can do anything in anytime including
translation-time and execution-time.

>
> > IIRC, the Standard requires an implementation not to fail to
> > translate and to execute a program unless every possible execution
> > of the program results in undefined behavior; if every possible
> > execution of a program results in undefined behavior, then an
> > implementation is allowed to fail to translate it.
>
> Which section of the standard says so?
>

A DR that's normative. I think we don't need to discuss on this issue
unless the Standard is not defective in this regard.

IIRC,
- If every possible execution of a program results in undefined
behavior, then the program is not s. c.
- The implementation is not allowed to fail translating or to
executing a program just because some of its possible executions
results in undefined behavior.
- If an expression appears in which a constant expression is required
and the evaluation of the expression results in UB, then the program
is not s. c.

Of course, the provisions of the conformance clause and the
requirements of the entire Standard still apply effectively.

#include <stdio.h>

int foo(int a)
{
if (a == 'x') return 1 / 0;
else return 0;
}

int main(void)
{
return foo(getchar());
}

The expression 1 / 0 *can* cause undefined behavior, but the context
in which it appears doesn't require a constant expression. The program
results in undefined behavior when the return value of getchar()
compare equal to 'x'. But it's just some possible execution of the
program.

int func(void);
double func(int a)
{
return 3.14159;
}

int main(void)
{
return 0;
}

Now, this program is not s. c. since it violates the requirements of
the Standard. An implementation can fail to translate this program.

Jun Woong

unread,
Nov 5, 2002, 6:55:44 PM11/5/02
to
"Jun Woong" <myco...@hanmail.net> wrote in message
news:IFYx9.839$5o4....@news.hananet.net...
[...]

>
> A DR that's normative. I think we don't need to discuss on this issue
> unless the Standard is not defective in this regard.
>

Correction:

"unless the Standard is not defective ..." should read as "unless the
Standard is defective"

Sorry.

Christian Bau

unread,
Nov 5, 2002, 7:20:40 PM11/5/02
to
In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,
Tak-Shing Chan <es...@city.ac.uk> wrote:

Try this one:

int main (void)
{
#pragma undefined behaviour
return 0;
}

E. Gibbons

unread,
Nov 5, 2002, 7:07:52 PM11/5/02
to
In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,

Tak-Shing Chan <es...@city.ac.uk> wrote:
>On 5 Nov 2002, E. Gibbons wrote:
>
>> #include <stdio.h>
>>
>> int main(void)
>> {
>> f(getchar()=='y');
>> return 0;
>> return 1; /*NOTREACHED*/
>> }
>>
>> (And the rest same as above.)
>
> You now have two distinct execution paths for this program:
>one ``uses'' the if part while the other ``uses'' the else part.

But the path that "uses" the if part and doesn't "use" the else part,
by your definition of "use", is still affected if the else is removed.

>> All my points above still hold for this modified program, and I hope this
>> lays to rest your "as-if" diversion. Of course, in *my* interpretation,
>> "as-if" doesn't matter because "use" refers to constructs that are "used"
>> in the *source code* of the program, prior to compilation, execution, or
>> any applicability of "as-if". Anyway, please address my points in light
>> of this new program.
>
> If this were true, then you should be able to state whether
>the following program invokes undefined behavior or not (prior to
>compilation or execution):

That doesn't follow at all.

> #include <stdio.h>
> int main() { char s[9]; gets(s); puts(s); }
>
> Can you do this?

No, of course not. That proves nothing.

But I *can* tell you whether it "uses" gets() or not: it does. It's using
it already, as it sits there on the page. I don't have to execute
anything for this *source code program* to "use" the construct known as
gets().

Please address my points.

--Ben

--

Andreas Kähäri

unread,
Nov 5, 2002, 7:28:30 PM11/5/02
to
Submitted by "Christian Bau" to comp.lang.c:
> In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,
[cut]

>
> Try this one:
>
> int main (void)
> {
> #pragma undefined behaviour

I believe that this will invoke implementation-defined
behaviour, not undefined behaviour. I'm not sure what you
wanted to say with this.

> return 0;
> }


--
Andreas Kähäri --==::{ Have a Unix: netbsd.org
--==::{ This post ends with :wq

Douglas A. Gwyn

unread,
Nov 5, 2002, 11:37:11 PM11/5/02
to
Martin Dickopp wrote:
>>> int main(void) { return 0 && (1 / 0); }
> Now I'm completely confused. If you agree that there is no distinction
> between translation-time and execution-time undefined behavior, how
> can this program be strictly conforming?

How could it not be? The division is not evaluated.

Bruce Wheeler

unread,
Nov 6, 2002, 6:21:01 AM11/6/02
to
On Wed, 06 Nov 2002 09:17:52 +0000, Christian Bau
<christ...@freeserve.co.uk> wrote:

>In article <slrnasgo...@otaku.freeshell.org>,


> Andreas Kähäri <a...@freeshell.org.REMOVE> wrote:
>
>> Submitted by "Christian Bau" to comp.lang.c:
>> > In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,
>> [cut]
>> >
>> > Try this one:
>> >
>> > int main (void)
>> > {
>> > #pragma undefined behaviour
>>
>> I believe that this will invoke implementation-defined
>> behaviour, not undefined behaviour. I'm not sure what you
>> wanted to say with this.
>

>Your believe is wrong. Of course this does _NOT_ invoke implementation
>defined behaviour. Nowhere in the C standard will you find that an
>implementation has to define what it will do if the source code contains
>a line
>
> #pragma undefined behaviour
>
>All pragmas apart from the three or four defined in the C99 Standard
>will invoke undefined behaviour. Check your compiler manual. Does it
>define the behaviour for this pragma or not? Didn't think so. What you
>have got here is an example of _undefined behaviour at compile time_.
>

restoring comp.std.c to the list:

According to the standard, it is implementation defined.

6.10.6 Pragma directive
Semantics
1 A preprocessing directive of the form
# pragma pp-tokens opt new-line
where the preprocessing token STDC does not immediately follow pragma in
the directive (prior to any macro replacement)146) causes the
implementation to behave in an implementation-defined manner. The
behavior might cause translation to fail or cause the translator or the
resulting program to behave in a non-conforming manner. Any such
pragma that is not recognized by the implementation is ignored.

Regards,
Bruce Wheeler

Dan Pop

unread,
Nov 6, 2002, 6:31:59 AM11/6/02
to

Not even at translation-time?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Jun Woong

unread,
Nov 6, 2002, 6:46:04 AM11/6/02
to

"Dan Pop" <Dan...@cern.ch> wrote in message
news:aqaujf$318$1...@sunnews.cern.ch...

> In <3DC89C77...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
>
> >Martin Dickopp wrote:
> >>>> int main(void) { return 0 && (1 / 0); }
> >> Now I'm completely confused. If you agree that there is no distinction
> >> between translation-time and execution-time undefined behavior, how
> >> can this program be strictly conforming?
> >
> >How could it not be? The division is not evaluated.
>
> Not even at translation-time?
>

As I understand, yes; the implementation is not free to fail
translating the construct. The expression following the "return"
statement need not to be a constant expression. See my previous
posting in this thread.

pete

unread,
Nov 6, 2002, 6:57:24 AM11/6/02
to

My MSVC++5.0 compiler won't compile my_example.c

Is my compiler broken ?

/* BEGIN my_example.c */

int main(void) {int zero = 0; return zero && (1 / 0); }

/* END my_example.c */

my_example.c(3) : error C2124: divide or mod by zero

--
pete

Jun Woong

unread,
Nov 6, 2002, 7:37:37 AM11/6/02
to
"pete" <pfi...@mindspring.com> wrote in message
news:3DC903...@mindspring.com...

> Jun Woong wrote:
> >
> > "Tak-Shing Chan" <es...@city.ac.uk> wrote in message
> > news:Pine.GSO.4.21.0211051820230.5385-100000@swindon...
> > > On 5 Nov 2002, Dan Pop wrote:
> > >
> > > > It is not clear (to me, at least), whether the standard makes a
> > > > distinction between translation-time undefined behaviour
> > > > and execution-time undefined behaviour.
> > >
> > > It is clear (to everyone else) that the standard only cares
> > > about execution-time undefined behaviour.
> >
> > Dan is right. There is no distinction between translation-time UB and
> > execution-time UB.
> >
> > > Here is a strictly
> > > conforming program:
> > >
> > > int main(void) { return 0 && (1 / 0); }
> > >
> >
> > Yes, this is a s. c. program. IIRC, the Standard requires an
> > implementation not to fail to translate and to execute a program
> > unless every possible execution of the program results in undefined
> > behavior; if every possible execution of a program results in
> > undefined behavior, then an implementation is allowed to fail to
> > translate it.
>
> My MSVC++5.0 compiler won't compile my_example.c
>
> Is my compiler broken ?
>

Yes. My answer is not from my own interpretation; it's from the
Committee. I don't recall the exact document number but you can find
the identical asnwer from a DR.

Why does MSVC have so many non-conforming features? :(

[skip the example and error message]

James Kuyper Jr.

unread,
Nov 6, 2002, 7:43:34 AM11/6/02
to
Dan Pop wrote:
> In <3DC89C77...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
>
>
>>Martin Dickopp wrote:
>>
>>>>> int main(void) { return 0 && (1 / 0); }
>>>>
>>>Now I'm completely confused. If you agree that there is no distinction
>>>between translation-time and execution-time undefined behavior, how
>>>can this program be strictly conforming?
>>
>>How could it not be? The division is not evaluated.
>
>
> Not even at translation-time?

If the compiler pre-evaluates the expression, it must pre-evalute it
correctly, respecting the short-circuiting properties of &&.

In a case where the branch depends upon data processed at run-time, the
compiler must defer the undefined consequences of pre-computing 1/0,
until after it has verified that the branch was taken which actually
results in that computation; if it can't defer those consequences, its
not allowed to pre-compute it.

Martin Dickopp

unread,
Nov 6, 2002, 7:50:57 AM11/6/02
to
In comp.lang.c Jun Woong <myco...@hanmail.net> wrote:
> - The implementation is not allowed to fail translating or to
> executing a program just because some of its possible executions
> results in undefined behavior.

Sorry, but I still don't see how this assumption can be derived from
the words of the standard.

Martin

Jun Woong

unread,
Nov 6, 2002, 8:05:32 AM11/6/02
to

"Martin Dickopp" <firefl...@gmx.net> wrote in message
news:aqb37h$tho$01$1...@news.t-online.com...

The Committee's answer from the DR system has the equivalent force
to the wording of the Standard itself.

Jeremy Yallop

unread,
Nov 6, 2002, 8:29:44 AM11/6/02
to
Bill Godfrey wrote:

> "Jun Woong" <myco...@hanmail.net> wrote:
> > > My MSVC++5.0 compiler won't compile my_example.c
> > > Is my compiler broken ?
>
> > Yes. My answer is not from my own interpretation; it's from the
> > Committee. I don't recall the exact document number but you can find
> > the identical asnwer from a DR.
>
> If reporting the snipped example as an error is broken, then I'll take
> broken over "fixed", thank you very much.

Reporting the error is fine. Refusal to translate the program is not.

Jeremy.

Bill Godfrey

unread,
Nov 6, 2002, 8:20:51 AM11/6/02
to
"Jun Woong" <myco...@hanmail.net> wrote:
> > My MSVC++5.0 compiler won't compile my_example.c
> > Is my compiler broken ?

> Yes. My answer is not from my own interpretation; it's from the
> Committee. I don't recall the exact document number but you can find
> the identical asnwer from a DR.

If reporting the snipped example as an error is broken, then I'll take


broken over "fixed", thank you very much.

Bill, IMHO.

Tak-Shing Chan

unread,
Nov 6, 2002, 8:22:32 AM11/6/02
to
On 6 Nov 2002, E. Gibbons wrote:

> In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,
> Tak-Shing Chan <es...@city.ac.uk> wrote:
>>On 5 Nov 2002, E. Gibbons wrote:
>> You now have two distinct execution paths for this program:
>>one ``uses'' the if part while the other ``uses'' the else part.
>
> But the path that "uses" the if part and doesn't "use" the else part,
> by your definition of "use", is still affected if the else is removed.

You are saying that ``A doesn't use B but is still affected
if B is removed,'' which contradicts the as-if rule.

>> If this were true, then you should be able to state whether
>>the following program invokes undefined behavior or not (prior to
>>compilation or execution):
>
> That doesn't follow at all.

It does follow, because given your definition of ``use'',
you should be able to tell it from source code alone.

>> #include <stdio.h>
>> int main() { char s[9]; gets(s); puts(s); }
>>
>> Can you do this?
>
> No, of course not. That proves nothing.

If you cannot do this, then it is a proof that your
definition of ``use'' is flawed.

> But I *can* tell you whether it "uses" gets() or not: it does. It's using
> it already, as it sits there on the page. I don't have to execute
> anything for this *source code program* to "use" the construct known as
> gets().

Irrelevant. Without knowing the user input in advance, you
cannot even try to tell me whether it ``uses'' s[5] or not.

> Please address my points.

I have already done so.

Tak-Shing

pete

unread,
Nov 6, 2002, 9:12:58 AM11/6/02
to

I don't know why.
Thank you.

--
pete

Martin Dickopp

unread,
Nov 6, 2002, 9:53:41 AM11/6/02
to
In comp.lang.c Jun Woong <myco...@hanmail.net> wrote:
> "Martin Dickopp" <firefl...@gmx.net> wrote in message
> news:aq98ed$h7r$03$1...@news.t-online.com...
>> In comp.lang.c Jun Woong <myco...@hanmail.net> wrote:
>> > IIRC, the Standard requires an implementation not to fail to
>> > translate and to execute a program unless every possible execution
>> > of the program results in undefined behavior; if every possible
>> > execution of a program results in undefined behavior, then an
>> > implementation is allowed to fail to translate it.
>>
>> Which section of the standard says so?
>
> A DR that's normative.

Are you refering to DR#247?

Martin

Jun Woong

unread,
Nov 6, 2002, 10:56:16 AM11/6/02
to

"Martin Dickopp" <firefl...@gmx.net> wrote in message
news:aqbadl$jir$06$1...@news.t-online.com...

No, DR#247 deals with the connection between use of values and
behaviors, which is irrelevant to this problem.

See DR#109 and DR#132.

http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_109.html
http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_132.html

Martin Dickopp

unread,
Nov 6, 2002, 1:20:10 PM11/6/02
to

Thanks!

I have not found these because I misunderstood how the standardization
process works. Since I didn't know that DRs from 1993 are a normative
part of the current (1999) C standard, I didn't even look at these old
DRs. The fact that the WG14 www site has a page entitled "WG14 Defect
Report Summary for ISO/IEC 9899:1999", which does not include these old
reports, made me believe that older DRs are not relevant.

Martin

E. Gibbons

unread,
Nov 6, 2002, 2:12:25 PM11/6/02
to
In article <Pine.GSO.4.21.0211061258370.4297-100000@swindon>,

Tak-Shing Chan <es...@city.ac.uk> wrote:
>On 6 Nov 2002, E. Gibbons wrote:
>
>> In article <Pine.GSO.4.21.0211052332020.16848-100000@swindon>,
>> Tak-Shing Chan <es...@city.ac.uk> wrote:
>>>On 5 Nov 2002, E. Gibbons wrote:
>>> You now have two distinct execution paths for this program:
>>>one ``uses'' the if part while the other ``uses'' the else part.
>>
>> But the path that "uses" the if part and doesn't "use" the else part,
>> by your definition of "use", is still affected if the else is removed.
>
> You are saying that ``A doesn't use B but is still affected
>if B is removed,'' which contradicts the as-if rule.

No, *you* are saying A doesn't use B, and *I* am making the point that it
*must* use B, because if B is removed, the behaviour changes. It's all
plainly quoted above. Try to keep the arguments straight, here!

>>> If this were true, then you should be able to state whether
>>>the following program invokes undefined behavior or not (prior to
>>>compilation or execution):
>>
>> That doesn't follow at all.
>
> It does follow, because given your definition of ``use'',
>you should be able to tell it from source code alone.

But you weren't asking about "use". As I said, quoted below, I *can*
tell whether it "uses" a given construct, by my interpretation of "use".

>>> #include <stdio.h>
>>> int main() { char s[9]; gets(s); puts(s); }
>>>
>>> Can you do this?
>>
>> No, of course not. That proves nothing.
>
> If you cannot do this, then it is a proof that your
>definition of ``use'' is flawed.

No, it is a proof that a program can "use" a construct, according to
my interpretation of "use", without *executing* that construct, which
seems to be what your interpretation of "use" amounts to.

>> But I *can* tell you whether it "uses" gets() or not: it does. It's using
>> it already, as it sits there on the page. I don't have to execute
>> anything for this *source code program* to "use" the construct known as
>> gets().
>
> Irrelevant. Without knowing the user input in advance, you
>cannot even try to tell me whether it ``uses'' s[5] or not.

Yes, I can, and in fact I did tell you so. Please read my quoted text
above carefully.

>> Please address my points.
>
> I have already done so.

No, you haven't. You have demonstrated rather clearly that you don't
understand my point.

Here, let's try some fresh code, with even less ambiguity.

#include <stdio.h>

int main(void)
{
char * p;

if(0) {
gets(p);
}
return 0;
}

By my definition, this program "uses" gets(), although it will never
*execute* it, and thus does not invoke UB. And that's why it needs to
#include <stdio.h>.

By your definition, it does not "use" gets(). Why, then, does it
need to "use" stdio.h?

What if a construct is optimized out? How can you tell whether it is
"used" or not?

What if you compile the program, but never actually run it? Does it
"use" nothing, then? What if you only run it if a radioactive decay
event causes a cat to die in an underground lab somewhere? What if
you run 3000 copies in parallel? Does your program "use" main() 3000
times, then (but only while they're running)?

Your definition amounts to "executes the construct", mine amounts to
"contains the construct". Yours is awkward, and is *fundamentally
undecideable* in the general case; and it loses the distinction between
"contains" and "executes"; and, it falls down completely for constructs
that simply are *not* executable, such as comments, preprocessor
directives, etc.. So, although neither of us knows for certain which
sense the Standard intended in the original quote, I think my sense
of the word makes more sense, is more decideable, and has more value,
in general.

But as they say, YMMV. The real question is what the *Standard* means
by "use", and all we have shown here is that two non-experts disagree.

--Ben

--

James Kuyper

unread,
Nov 6, 2002, 3:27:50 PM11/6/02
to

That's actually a matter which has been hotly debated. For C90 DR
decisions which provide official interpretations of the wording of the
standard, if none of the relevant text changed in C99, than neither did
the interpretation.

However, many DR decisions are based upon text which did change. Those
decisions can't be carried over to C99. For example, the resolution to
DR005 says in part "No, a strictly conforming program may not contain a
pragma directive." With the addition of the new standard pragmas in C99,
this conclusion has to be false.
It can sometimes be difficult to determine precisely which text the
committee based it's decisions on - when that's the case, it's
correspondingly difficult to guess whether or not the decision should
carry over.

Of course, some DR decisions went beyond the actual text of the
standard. The committee had a chance to add supporting text for those
decisions into the new version of the standard; if it failed to do so,
that should be considered as evidence that the C90 decision does not
apply to C99.
However, this is a very controversial area; primarily because there's
disagreement about which DR decisions fall into this category.

Douglas A. Gwyn

unread,
Nov 6, 2002, 10:55:18 PM11/6/02
to
Dan Pop wrote:
> In <3DC89C77...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
>>>>> int main(void) { return 0 && (1 / 0); }
>> The division is not evaluated.
> Not even at translation-time?

No, it must not be.

Dan Pop

unread,
Nov 7, 2002, 5:04:26 AM11/7/02
to

Even if we replace this trivial example by something like:

int main(int argc, char **argv) { return argc && (1 / 0); }

Alexander Terekhov

unread,
Nov 7, 2002, 7:21:15 AM11/7/02
to

Dan Pop wrote:
>
> In <3DC9E426...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
>
> >Dan Pop wrote:
> >> In <3DC89C77...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
> >>>>>> int main(void) { return 0 && (1 / 0); }
> >>> The division is not evaluated.
> >> Not even at translation-time?
> >
> >No, it must not be.
>
> Even if we replace this trivial example by something like:
>
> int main(int argc, char **argv) { return argc && (1 / 0); }

Who's the idiot here, Dan?

regards,
alexander.

James Kuyper Jr.

unread,
Nov 7, 2002, 8:11:37 AM11/7/02
to
Dan Pop wrote:
> In <3DC9E426...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
>
>
>>Dan Pop wrote:
>>
>>>In <3DC89C77...@null.net> "Douglas A. Gwyn" <DAG...@null.net> writes:
...

>>>>The division is not evaluated.
>>>
>>>Not even at translation-time?
>>
>>No, it must not be.
>
>
> Even if we replace this trivial example by something like:
>
> int main(int argc, char **argv) { return argc && (1 / 0); }

An implementation can evaluate the 1/0 at translation time in this case,
only if the implementation can guarantee that argc is non-zero. Since
it's up to the implementation how argc acquires it's non-negative value,
it's quite possible that the implementation can guarantee this.

Tak-Shing Chan

unread,
Nov 7, 2002, 9:16:00 AM11/7/02
to
On 6 Nov 2002, E. Gibbons wrote:

> No, *you* are saying A doesn't use B, and *I* am making the point that it
> *must* use B, because if B is removed, the behaviour changes. It's all

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Wrong. The removal of B does not change the behavior of A:
the behavior of ``if (1) f(); else g();'' is exactly the same as
the behavior of ``if (1) f();''.

> No, it is a proof that a program can "use" a construct,

You have not proved anything yet. What you have done so
far, is to invent a definition of your own, which the standard
disagrees with.

> Yes, I can, and in fact I did tell you so. Please read my quoted text

You did not. Does it ``use'' s[5]? I found no answer in
your previous posts.

> #include <stdio.h>
>
> int main(void)
> {
> char * p;
>
> if(0) {
> gets(p);
> }
> return 0;
> }
>
> By my definition, this program "uses" gets(), although it will never
> *execute* it, and thus does not invoke UB. And that's why it needs to
> #include <stdio.h>.

It does not follow.

> By your definition, it does not "use" gets(). Why, then, does it
> need to "use" stdio.h?

It does not need to. Please read the relevant DRs (see
Jun Woong's posts). According to the DR responses, the following
translation unit *must* be successfully translated:

int checkup()
{
if (0) printf("Printing.\n"); /* Missing prototype */
return 2 || 1 / 0; /* Division by zero */
}

Clearly, printf() is not used here, otherwise it contradicts
with the committee's official response.

Tak-Shing

Tak-Shing Chan

unread,
Nov 7, 2002, 9:23:06 AM11/7/02
to
On Thu, 7 Nov 2002, James Kuyper Jr. wrote:

> Dan Pop wrote:
>> int main(int argc, char **argv) { return argc && (1 / 0); }
>
> An implementation can evaluate the 1/0 at translation time in this case,
> only if the implementation can guarantee that argc is non-zero. Since
> it's up to the implementation how argc acquires it's non-negative value,
> it's quite possible that the implementation can guarantee this.

Since the as-if rule is located under ``program execution'',
I believe that precomputation does not count as evaluation.

Tak-Shing

James Kuyper Jr.

unread,
Nov 7, 2002, 9:45:44 AM11/7/02
to

Under the as-if rule, pre-computation is allowed only if it produces
effects which are indistinguishable from effects which would also be
legal if it performed the evaluation at run-time, instead. It's not
allowed to make the program's translation and execution fail because of
that pre-computation, unless and until it can guarantee that argc is
non-zero. That could be guaranteed at compile time, for some
implementations.

However, consider an implementation that documents a way of invoking the
program which guarantees argc==0. Such an implementation cannot fail to
correctly translate and execute this program, if it is actually invoked
in that fashion (modulo implementation limits issues).

t...@cs.ucr.edu

unread,
Nov 7, 2002, 11:22:40 AM11/7/02
to
In comp.std.c James Kuyper Jr. <kuy...@wizard.net> wrote:
+ Tak-Shing Chan wrote:
+ > On Thu, 7 Nov 2002, James Kuyper Jr. wrote:
+ >
+ >
+ >>Dan Pop wrote:
+ >>
+ >>> int main(int argc, char **argv) { return argc && (1 / 0); }
+ >>
+ >>An implementation can evaluate the 1/0 at translation time in this case,
+ >>only if the implementation can guarantee that argc is non-zero. Since
+ >>it's up to the implementation how argc acquires it's non-negative value,
+ >>it's quite possible that the implementation can guarantee this.
+ >
+ >
+ > Since the as-if rule is located under ``program execution'',
+ > I believe that precomputation does not count as evaluation.
+
+ Under the as-if rule, pre-computation is allowed only if it produces
+ effects which are indistinguishable from effects which would also be
+ legal if it performed the evaluation at run-time, instead. It's not
+ allowed to make the program's translation and execution fail because of
+ that pre-computation, unless and until it can guarantee that argc is
+ non-zero. That could be guaranteed at compile time, for some
+ implementations.
+
+ However, consider an implementation that documents a way of invoking the
+ program which guarantees argc==0. Such an implementation cannot fail to
+ correctly translate and execute this program, if it is actually invoked
+ in that fashion (modulo implementation limits issues).

I agree, but I suspect that fewer will agree if we modify the example
slightly:

int main(int argc, char **argv) { return argc && (*0 = 1); }
^
assignment

Assuming that argc can be zero, must the implementation translate this
program? I.e., is "*0" a legitimate lvalue here?

Tom Payne

Jeremy Yallop

unread,
Nov 7, 2002, 11:56:41 AM11/7/02
to
* t...@cs.ucr.edu

| int main(int argc, char **argv) { return argc && (*0 = 1); }
| ^
| assignment
|
| Assuming that argc can be zero, must the implementation translate this
| program? I.e., is "*0" a legitimate lvalue here?

No, it's a constraint violation. '0' doesn't have pointer type.

Jeremy.

t...@cs.ucr.edu

unread,
Nov 7, 2002, 12:05:56 PM11/7/02
to
In comp.std.c E. Gibbons <euph...@u.washington.edu> wrote: [...] +
All my points above still hold for this modified program, and I hope
this + lays to rest your "as-if" diversion. Of course, in *my*
interpretation, + "as-if" doesn't matter because "use" refers to
constructs that are "used" + in the *source code* of the program,
prior to compilation, execution, or + any applicability of "as-if".

The term "use" in the definition of "undefined behavior" cannot refer
exclusively to static attributes of the program. For two reasons,
there is no way that static analysis can reliably determine whether or
not division-by-zero will occur at run time.

Reason #1: There is no way to predict input:

int n;
n = user_input();
1/n;

Reason #2: Even when there is no external input, determining whether
or not a given variable will ever take on the value zero at a given
point in the program is equivalent to the halting problem, i.e., there
is no algorithm for determining whether or not this situaiton will
occur.

Tom Payne

Douglas A. Gwyn

unread,
Nov 7, 2002, 3:08:01 PM11/7/02
to
Dan Pop wrote:
> Even if we replace this trivial example by something like:
> int main(int argc, char **argv) { return argc && (1 / 0); }

If argc might be zero, then the division must not be evaluated
at translation time (or at any rate the program must be
translated and made ready for execution). If the implementation
is such that argc can never be zero at run time, then the
division may be performed at translation time, and among the
possible allowed behaviors would be failure to produce an
executable image, plus warning about the division by zero.

I don't see what is so hard to understand: execution occurs
at run time, not translation time (except for constant
expressions, which are such only in contexts where they are
required to be such); and if an implementation can determine
with certainty that undefined behavior would occur when the
program is executed, it has the option to not execute it.

Douglas A. Gwyn

unread,
Nov 7, 2002, 3:12:28 PM11/7/02
to
Bill Godfrey wrote:
> If reporting the snipped example as an error is broken,
> then I'll take broken over "fixed", thank you very much.

Why? The program had perfectly reasonable, well-defined
properties, but that compiler refused to accept it. Now,
a *warning* about possible division by zero might be
useful, but not an outright refusal to compile.

E. Gibbons

unread,
Nov 7, 2002, 4:40:41 PM11/7/02
to
In article <Pine.GSO.4.21.0211071323340.15895-100000@swindon>,

Tak-Shing Chan <es...@city.ac.uk> wrote:
>On 6 Nov 2002, E. Gibbons wrote:
>
>> No, *you* are saying A doesn't use B, and *I* am making the point that it
>> *must* use B, because if B is removed, the behaviour changes. It's all
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Wrong. The removal of B does not change the behavior of A:
>the behavior of ``if (1) f(); else g();'' is exactly the same as
>the behavior of ``if (1) f();''.

But it's not the same as "if(1) f(); g();", which was what was under
discussion. "B" is "else". Read the thread.

>> No, it is a proof that a program can "use" a construct,
>
> You have not proved anything yet. What you have done so
>far, is to invent a definition of your own, which the standard
>disagrees with.

You have not shown that the standard disagrees. If you can do so,
do it now.

>> Yes, I can, and in fact I did tell you so. Please read my quoted text
>
> You did not. Does it ``use'' s[5]? I found no answer in
>your previous posts.

I answered that *twice* already.

>> #include <stdio.h>
>>
>> int main(void)
>> {
>> char * p;
>>
>> if(0) {
>> gets(p);
>> }
>> return 0;
>> }
>>
>> By my definition, this program "uses" gets(), although it will never
>> *execute* it, and thus does not invoke UB. And that's why it needs to
>> #include <stdio.h>.
>
> It does not follow.
>
>> By your definition, it does not "use" gets(). Why, then, does it
>> need to "use" stdio.h?
>
> It does not need to. Please read the relevant DRs (see
>Jun Woong's posts). According to the DR responses, the following
>translation unit *must* be successfully translated:
>
> int checkup()
> {
> if (0) printf("Printing.\n"); /* Missing prototype */
> return 2 || 1 / 0; /* Division by zero */
> }
>
> Clearly, printf() is not used here, otherwise it contradicts
>with the committee's official response.

Well, I guess the gcc people haven't read that DR (which DR is it,
please?):

gemini[pts/3]:~/tmp$ cat checkup.c


int checkup()
{
if (0) printf("Printing.\n"); /* Missing prototype */
return 2 || 1 / 0; /* Division by zero */
}

gemini[pts/3]:~/tmp$ gcc -ansi -pedantic -Wall -W -Werror -O2 -c checkup.c -o checkup.o
cc1: warnings being treated as errors
checkup.c: In function `checkup':
checkup.c:3: warning: implicit declaration of function `printf'
gemini[pts/3]:~/tmp$ ls -l checkup.*
-rw-r--r-- 1 bketcham bketcham 157 Nov 7 13:34 checkup.c

--Ben


--

Barry Margolin

unread,
Nov 7, 2002, 5:35:32 PM11/7/02
to
In article <aqemkp$1sjo$1...@nntp6.u.washington.edu>,

E. Gibbons <euph...@u.washington.edu> wrote:
>Well, I guess the gcc people haven't read that DR (which DR is it,
>please?):
>
>gemini[pts/3]:~/tmp$ cat checkup.c
> int checkup()
> {
> if (0) printf("Printing.\n"); /* Missing prototype */
> return 2 || 1 / 0; /* Division by zero */
> }
>gemini[pts/3]:~/tmp$ gcc -ansi -pedantic -Wall -W -Werror -O2 -c
>checkup.c -o checkup.o
>cc1: warnings being treated as errors
>checkup.c: In function `checkup':
>checkup.c:3: warning: implicit declaration of function `printf'
>gemini[pts/3]:~/tmp$ ls -l checkup.*
>-rw-r--r-- 1 bketcham bketcham 157 Nov 7 13:34 checkup.c

It was merely warning about the missing prototype, but you made use of an
option that tells it to treat warning-level situations as errors (it even
told you that it was doing that). Why would you expect standard-conforming
behavior when you've specifically told it to do this?

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

James Kuyper

unread,
Nov 7, 2002, 5:44:02 PM11/7/02
to
"E. Gibbons" wrote:
>
> In article <Pine.GSO.4.21.0211071323340.15895-100000@swindon>,
> Tak-Shing Chan <es...@city.ac.uk> wrote:
...

> > It does not need to. Please read the relevant DRs (see
> >Jun Woong's posts). According to the DR responses, the following
> >translation unit *must* be successfully translated:
...

> Well, I guess the gcc people haven't read that DR (which DR is it,
> please?):

Check back on the other branch of this thread - the one that doesn't
have you and Tak-Shing arguing back and forth. Jun Woong's message dated
"Thu, 7 Nov 2002 00:56:16 +0900" contains links to the relevant DRs.

> gemini[pts/3]:~/tmp$ cat checkup.c
> int checkup()
> {
> if (0) printf("Printing.\n"); /* Missing prototype */
> return 2 || 1 / 0; /* Division by zero */
> }
> gemini[pts/3]:~/tmp$ gcc -ansi -pedantic -Wall -W -Werror -O2 -c checkup.c -o checkup.o
> cc1: warnings being treated as errors
> checkup.c: In function `checkup':
> checkup.c:3: warning: implicit declaration of function `printf'

You told it to treat warnings as errors; that's not one of the options
you can use if you want to invoke gcc in a fully conforming mode. With
that option turned off, it warns about a great many things, some of
which are perfectly legal; but it goes ahead and compiles the code
anyway, so it is conforming. With that option turned on, it refuses to
compile those same things, including the ones that are perfectly legal,
making it no longer a conforming implementation.

Chris Torek

unread,
Nov 8, 2002, 2:12:35 AM11/8/02
to
In article <aqe6hk$7fa$1...@glue.ucr.edu> <t...@cs.ucr.edu> wrote:
>The term "use" in the definition of "undefined behavior" cannot refer
>exclusively to static attributes of the program. For two reasons,
>there is no way that static analysis can reliably determine whether or
>not division-by-zero will occur at run time.
>
> Reason #1: There is no way to predict input:
>
> int n;
> n = user_input();
> 1/n;
>
> Reason #2: Even when there is no external input, determining whether
> or not a given variable will ever take on the value zero at a given
> point in the program is equivalent to the halting problem, i.e., there
> is no algorithm for determining whether or not this situaiton will
> occur.

These are both valid general-case arguments, i.e., there exist
programs and inputs for which they are true. They are not valid
specific-case arguments, i.e., there may exist other programs (for
case #2) or implementations (for case #1) where the results *can*
be predicted in advance, even as far ahead as compile-time.

(For instance, a program that uses scanf("%d", &n) to read an
integer from stdin might be absolutely guaranteed to get EOF every
time, leaving "n" unchanged, on some implementation. The
compiler implementor simply "knows" that stdin is always connected
to the equivalent of /dev/null, and all attempts to freopen() it
fail, and so on.)

Since the standard has to talk about general cases, this is just
a nit. :-)
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
Salt Lake City, UT, USA Domain: to...@bsdi.com
http://67.40.109.61/torek/ (for the moment)
(you probably cannot email me -- spam has effectively killed email)

Dan Pop

unread,
Nov 8, 2002, 4:18:25 AM11/8/02
to

The point is that this conclusion cannot be drawn *exclusively* from the
text of the standard (you also have to read the minds of the committee
members or some DRs filed against an obsolete version of the standard).

The purpose of my questions was to get the issue fully clarified,
for the benefit of everyone following this discussion.

The above-mentioned DRs have provided ample proof that the text of C89
was defective in that area. Yet, the committee decided not to take any
corrective action(s) in C99. Any good reasons for this decision?

Dan Pop

unread,
Nov 8, 2002, 4:43:11 AM11/8/02
to
In <aqemkp$1sjo$1...@nntp6.u.washington.edu> euph...@u.washington.edu (E. Gibbons) writes:

>Well, I guess the gcc people haven't read that DR (which DR is it,
>please?):
>
>gemini[pts/3]:~/tmp$ cat checkup.c
> int checkup()
> {
> if (0) printf("Printing.\n"); /* Missing prototype */
> return 2 || 1 / 0; /* Division by zero */
> }
>gemini[pts/3]:~/tmp$ gcc -ansi -pedantic -Wall -W -Werror -O2 -c checkup.c -o checkup.o
>cc1: warnings being treated as errors
>checkup.c: In function `checkup':
>checkup.c:3: warning: implicit declaration of function `printf'
>gemini[pts/3]:~/tmp$ ls -l checkup.*
>-rw-r--r-- 1 bketcham bketcham 157 Nov 7 13:34 checkup.c

What makes you think that gcc is (or should be) a conforming translator
when using the -Werror option?

The semantics of the -Werror option are: "don't complete the
translation if a diagnostic was produced" and NOT "don't complete
the translation if a *required* diagnostic is produced". And both
-Wall and -W ask gcc to generate even more diagnostics that are NOT
required by the standard.

If you still don't get it, consider the following strictly conforming
program:

fangorn:~/tmp 28> cat test.c
int main()
{
int a = 'ab';
return 0;
}
fangorn:~/tmp 29> gcc -c -Werror test.c


cc1: warnings being treated as errors

test.c: In function `main':
test.c:3: warning: multi-character character constant
fangorn:~/tmp 30> echo $status
1
fangorn:~/tmp 31> ls test.o
ls: test.o: No such file or directory

Remove -Werror and the program is correctly translated.

Clive D. W. Feather

unread,
Nov 8, 2002, 7:37:12 AM11/8/02
to
In article <aqe609$97nja$1...@ID-114079.news.dfncis.de>, Jeremy Yallop
<jer...@jdyallop.freeserve.co.uk> writes

>No, it's a constraint violation. '0' doesn't have pointer type.

But it's a null pointer constant, so can be used as a pointer in at
least some cases.

--
Clive D.W. Feather, writing for himself | Home: <cl...@davros.org>
Tel: +44 20 8371 1138 (work) | Web: <http://www.davros.org>
Fax: +44 870 051 9937 | Work: <cl...@demon.net>
Written on my laptop; please observe the Reply-To address

Clive D. W. Feather

unread,
Nov 8, 2002, 7:37:58 AM11/8/02
to
In article <3DCAC821...@null.net>, Douglas A. Gwyn
<DAG...@null.net> writes

>I don't see what is so hard to understand: execution occurs
>at run time, not translation time (except for constant
>expressions, which are such only in contexts where they are
>required to be such);

Does this mean that WG14 has reached a conclusion on DR 261?

Clive D. W. Feather

unread,
Nov 8, 2002, 7:36:36 AM11/8/02
to
In article <aqbmgq$6d6$00$1...@news.t-online.com>, Martin Dickopp
<firefl...@gmx.net> writes

>Since I didn't know that DRs from 1993 are a normative
>part of the current (1999) C standard,

They aren't.

However, in a number of cases, if the question were asked again WG14
would be likely to give the same response. [Somewhere deep in my ToDo
list is an attempt to document these.]

Jeremy Yallop

unread,
Nov 8, 2002, 8:16:56 AM11/8/02
to
t...@cs.ucr.edu wrote:
>>> int main(int argc, char **argv) { return argc && (*0 = 1); }
>>> ^
>>> assignment
>>>
>>> Assuming that argc can be zero, must the implementation translate this
>>> program? I.e., is "*0" a legitimate lvalue here?

I replied:


>> No, it's a constraint violation. '0' doesn't have pointer type.

Clive D. W. Feather wrote:
> But it's a null pointer constant, so can be used as a pointer in at
> least some cases.

Yes, but not this one. Look at the context (reinstated).

Jeremy.

Francis Glassborow

unread,
Nov 8, 2002, 7:10:41 AM11/8/02
to
In message <3DCAC92C...@null.net>, Douglas A. Gwyn
<DAG...@null.net> writes


Not least because (if I understand the rules correctly) division by zero
could result in a NaN and no reason for the program to be aborted.

--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Richard Bos

unread,
Nov 8, 2002, 8:51:49 AM11/8/02
to
Jeremy Yallop <jer...@jdyallop.freeserve.co.uk> wrote:

> t...@cs.ucr.edu wrote:
> >>> int main(int argc, char **argv) { return argc && (*0 = 1); }
> >>> ^
> >>> assignment
> >>>
> >>> Assuming that argc can be zero, must the implementation translate this
> >>> program? I.e., is "*0" a legitimate lvalue here?
>

> >> No, it's a constraint violation. '0' doesn't have pointer type.
>

> > But it's a null pointer constant, so can be used as a pointer in at
> > least some cases.
>
> Yes, but not this one. Look at the context (reinstated).

That's the one-but-inner context. The _actual_ context is the
dereference operator; _it_ requires a pointer context, and thus the 0 is
interpreted as a null pointer constant, which is converted (at compile
time, most likely) to an actual null pointer. This null pointer is then
dereferenced.
As a result, this program is syntactically correct, and invokes
undefined behaviour only when argc != 0. If the compiler can determine
that argc will always be positive (for example, if it knows it will
always be able to supply argv[0]), it is AFAICT allowed not to compile
it; but if the compiler cannot be sure argc will never be 0, it _must_
compile this program.

Richard

t...@cs.ucr.edu

unread,
Nov 8, 2002, 8:37:03 AM11/8/02
to
In comp.std.c Richard Bos <r...@hoekstra-uitgeverij.nl> wrote:
+ Jeremy Yallop <jer...@jdyallop.freeserve.co.uk> wrote:
+
+> t...@cs.ucr.edu wrote:
+> >>> int main(int argc, char **argv) { return argc && (*0 = 1); }
+> >>> ^
+> >>> assignment
+> >>>
+> >>> Assuming that argc can be zero, must the implementation translate this
+> >>> program? I.e., is "*0" a legitimate lvalue here?
+>
+> >> No, it's a constraint violation. '0' doesn't have pointer type.
+>
+> > But it's a null pointer constant, so can be used as a pointer in at
+> > least some cases.
+>
+> Yes, but not this one. Look at the context (reinstated).
+
+ That's the one-but-inner context. The _actual_ context is the
+ dereference operator; _it_ requires a pointer context, and thus the 0 is
+ interpreted as a null pointer constant, which is converted (at compile
+ time, most likely) to an actual null pointer. This null pointer is then
+ dereferenced.
+ As a result, this program is syntactically correct, and invokes
+ undefined behaviour only when argc != 0. If the compiler can determine
+ that argc will always be positive (for example, if it knows it will
+ always be able to supply argv[0]), it is AFAICT allowed not to compile
+ it; but if the compiler cannot be sure argc will never be 0, it _must_
+ compile this program.

That's exactly how I see it. It follows, however, that "*0" is an
lvalue even though it does not designate an object. Lots of folks
seems to balk at that.

Tom Payne

Joona I Palaste

unread,
Nov 8, 2002, 9:06:28 AM11/8/02
to
t...@cs.ucr.edu scribbled the following
on comp.lang.c:

I do not understand this. How can *0 be a syntactically and
contextually valid expression? The unary * operator means the thing
that is stored at the address given by the operand. Here, it's clear
that the thing is stored at address 0, but no one bothered to tell what
type of thing it is: char, int, long...

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"It sure is cool having money and chicks."
- Beavis and Butt-head

James Kuyper Jr.

unread,
Nov 8, 2002, 9:39:43 AM11/8/02
to

Richard Bos wrote:
> Jeremy Yallop <jer...@jdyallop.freeserve.co.uk> wrote:
>
>
>>t...@cs.ucr.edu wrote:
>>
>>>>> int main(int argc, char **argv) { return argc && (*0 = 1); }
>>>>> ^
>>>>> assignment
>>>>>
>>>>>Assuming that argc can be zero, must the implementation translate this
>>>>>program? I.e., is "*0" a legitimate lvalue here?
>>>>
>>>>No, it's a constraint violation. '0' doesn't have pointer type.
>>>
>>>But it's a null pointer constant, so can be used as a pointer in at
>>>least some cases.
>>
>>Yes, but not this one. Look at the context (reinstated).
>
>
> That's the one-but-inner context. The _actual_ context is the
> dereference operator; _it_ requires a pointer context, and thus the 0 is
> interpreted as a null pointer constant, which is converted (at compile
> time, most likely) to an actual null pointer. This null pointer is then
> dereferenced.

Nice theory. Do you have supporting text for this interpretation?

There is no general rule that makes '0' convert to a pointer type just
because one is needed. There's just a few individual rules for
particular cases; and this isn't one of them. Those cases include
6.5.9p2 for == and !=, 6.5.15p3 for ?:, and 6.5.16p2 for the assignment
operators. Each of those paragraphs has a special option to allow for
one of the operands to be a null pointer constant while another operand
is a pointer.

Sections 6.5.9p5 and 6.5.15p3 each contain special wording describing
the kind of conversion you're talking about, to make the two operands
have the same type. Section 6.5.16 doesn't need special wording for null
pointer constants; the right operand is always converted to the type of
the left operand for assignment operators.

That's not a coincidence, or an oversight: there's no other operators
where it serves any useful purpose to allow null pointer constants as
operands. That's not quite true: function call operators also need to
convert null pointer constants to the appropriate pointer type, but in
that case conversion to the parameter's type is specified for all
prototyped arguments, whether or not they are null pointer constants.
Such implicit conversions most emphatically do NOT occur for
unprototyped arguments, including the variable arguments at the end of a
function declared as allowing such arguments. The expression
printf("%p", NULL) is not guaranteed to work as you might expect it to.
If the expansion of NULL is 0, it will be treated as an 'int', which is
the wrong type for %p (though it will work, by accident, on many platforms).

Section 6.5.3.2 describes the indirection operator, and the constraints
do not have an option allowing for general null pointer constants. Only
the ones (such as (void*)0) which actually have a pointer type are
allowed by the constraints (of course, the behavior is still undefined
if the operation is actually performed in that case). There is no
wording for that operator specifying the same kind of special handling
for null pointer constants that is described in 6.5.9p5 and 6.5.15p3.

t...@cs.ucr.edu

unread,
Nov 8, 2002, 9:20:29 AM11/8/02
to
In comp.std.c Joona I Palaste <pal...@cc.helsinki.fi> wrote:
[...]
+ I do not understand this. How can *0 be a syntactically and
+ contextually valid expression? The unary * operator means the thing
+ that is stored at the address given by the operand. Here, it's clear
+ that the thing is stored at address 0, but no one bothered to tell what
+ type of thing it is: char, int, long...

Good point. So, let's make that "*(int*)0" rather than "*0".

Tom Payne

Jun Woong

unread,
Nov 8, 2002, 10:01:33 AM11/8/02
to
"Richard Bos" <r...@hoekstra-uitgeverij.nl> wrote in message
news:3dcbc056...@news.nl.net...

> Jeremy Yallop <jer...@jdyallop.freeserve.co.uk> wrote:
>
> > t...@cs.ucr.edu wrote:
> > >>> int main(int argc, char **argv) { return argc && (*0 = 1); }
> > >>> ^
> > >>> assignment
> > >>>
> > >>> Assuming that argc can be zero, must the implementation translate
this
> > >>> program? I.e., is "*0" a legitimate lvalue here?
> >
> > >> No, it's a constraint violation. '0' doesn't have pointer type.
> >
> > > But it's a null pointer constant, so can be used as a pointer in at
> > > least some cases.
> >
> > Yes, but not this one. Look at the context (reinstated).
>
> That's the one-but-inner context. The _actual_ context is the
> dereference operator; _it_ requires a pointer context, and thus the 0 is
> interpreted as a null pointer constant, which is converted (at compile
> time, most likely) to an actual null pointer. This null pointer is then
> dereferenced.

Incorrect. You can never find the wording supporting your argument.
The unary operator doesn't qualify the context where a null pointer
constant is converted to a null pointer.

--
Jun, Woong (myco...@hanmail.net)
Dept. of Physics, Univ. of Seoul

Jun Woong

unread,
Nov 8, 2002, 10:04:39 AM11/8/02