undefined behaviour seems wrong and a big error

R

RoSsIaCrIiLoIA

Romeo Colacitti said:
Chris said:
If you have
int array[1];
then
array[-1] is an example of an lvalue which doesn't refer
to an object. The use of such an lvalue would be undefined behavior.

Again, apparently true in C99, but not (technically) in C89. But
this just means the C89 standard has a defect.

C99 is worse, because as per the said standard almost every expression
that doesn't resolve to an incomplete types or function type is an
LVALUE. So something like 2+3 is an lvalue in C99. I'll just modify
that errant sentence in the C99, it must obviously be a typo (they
forgot to mention that an lvalue "designates an object.")

Alas, it wasn't a typo. In C90, an lvalue is defined as "an
expression (with an object type or an incomplete type other than void)
that designates an object". The flaw in this definition, given
int *ptr;
the expression *ptr may or may not designate an object (it doesn't of
ptr==NULL, for example). So strictly speaking, you can't always
determine whether an expression is an lvalue until runtime, which
clearly was not the intent.

C99 attempted to correct this by dropping the absolute requirement
that an lvalue must designate an object; an lvalue is now "an
expression with an object type or an incomplete type other than void;
if an lvalue does not designate an object when it is evaluated, the
behavior is undefined." Strictly speaking, 42 is an lvalue (it's an
expression with an object type) -- and evaluating it invokes undefined
behavior. Again, this clearly was not the intent.

I don't are aware of compiler science but "undefined behaviour"
is WRONG, I don't see why "undefined behaviour" has to exist
The behaviour has to be only
1) Compiler do not accept the expression: error
or
2) Compiler accept the expression and every conforming compiler
translate that in the same "behaviour"
END

if someone write *s=++*s; and this is your "undefined behaviour"
compiler has not compile...
 
I

infobahn

RoSsIaCrIiLoIA said:
I don't are aware of compiler science

Then what makes you feel you are qualified to offer an opinion on it?
but "undefined behaviour"
is WRONG,

Yup, so don't invoke it.
I don't see why "undefined behaviour" has to exist

That much is obvious.
The behaviour has to be only
1) Compiler do not accept the expression: error
or
2) Compiler accept the expression and every conforming compiler
translate that in the same "behaviour"
END

Fine. Go write a language in which that behaviour is observed.
C isn't it.
if someone write *s=++*s; and this is your "undefined behaviour"
compiler has not compile...

Feel free to write your own C compiler, in which you diagnose
every occurrence of undefined behaviour in an arbitrary C program.
 
K

Kenny McCormack

RoSsIaCrIiLoIA said:
I don't are aware of compiler science but "undefined behaviour"
is WRONG, I don't see why "undefined behaviour" has to exist
The behaviour has to be only
1) Compiler do not accept the expression: error
or
2) Compiler accept the expression and every conforming compiler
translate that in the same "behaviour"
END

if someone write *s=++*s; and this is your "undefined behaviour"
compiler has not compile...

That's the philosophy of the C-like language known as "D"
(www.digitalmars.com). The stated idea of that language is that things
should be either right or wrong (not the endless shades of grey that is
the situation in C) and that the compiler is able to tell right from wrong.

Obviously, for better or worse, this is not the situation with C. I think
it would help a lot if those folks who come in and complain that C isn't
Java or Perl (or any other safety-belted language) would, whenever they see
"C" think (and see in their minds) "portable assembler". That would help
them realize how unlikely it is that C could be safety-belted.
 
S

SM Ryan

# >I don't are aware of compiler science but "undefined behaviour"
# >is WRONG, I don't see why "undefined behaviour" has to exist
# >The behaviour has to be only

You can extend any partial function which is undefined on part of its domain to being
a total function by making it a special value wherever it had been undefined. However
if the function is recursive and not recursively enumerable, there is no known
mechanism which can be guarenteed to find everywhere the partial function is undefined.
(Such a mechanism would be more powerful than a Turing machine.)

You can do a couple things. Declare the function total anyway; restrict yourself to
functions that are re or less powerful; or accept some things are undefined.
 
R

RoSsIaCrIiLoIA

I don't are aware of compiler science but "undefined behaviour"
is WRONG, I don't see why "undefined behaviour" has to exist
The behaviour has to be only
1) Compiler do not accept the expression: error
or
2) Compiler accept the expression and every conforming compiler
translate that in the same "behaviour"
END

if someone write *s=++*s; and this is your "undefined behaviour"
compiler has not compile...

the "undefined behaviour" is good and sensible only if it describe one
*extension* of the language *out the ansi standard*
 
I

infobahn

RoSsIaCrIiLoIA said:
the "undefined behaviour" is good and sensible only if it describe one
*extension* of the language *out the ansi standard*

Do you think the compiler should diagnose this code?

#include <stdio.h>

void foo(FILE *fp)
{
fflush(fp);
}

If so, why? If not, why not?
 
W

Walter

Kenny McCormack said:
That's the philosophy of the C-like language known as "D"
(www.digitalmars.com). The stated idea of that language is that things
should be either right or wrong (not the endless shades of grey that is
the situation in C) and that the compiler is able to tell right from
wrong.

Sometimes people misattribute the portability of Java to the fact that it
runs on a virtual machine. It isn't true, the real reason that Java code is
portable is the language designers made a major effort to eliminate
implementation defined, undefined, and unspecified behavior.

There's no reason that a native compiled language cannot be just as portable
as Java is.

Much of the implementation defined, etc., behaviors of C are legacies left
over from how early implementations differed. Some of it is from trying to
improve efficiency on some CPUs, such as whether char's are signed or not.
Portability of C code is achieved by carefully avoiding such things, and one
really has to know C well to do it successfully.

Perhaps the time has come for C (and C++) to make a pass through the
standard and take a hard look at each of these and get rid of as many as
possible. Getting rid of the order-of-evaluation problems of expressions is
probably a good start. The implementation signed-ness of chars is another
one. I don't believe the efficiency reasons for these being implementation
defined are valid any longer.

The D programming language falls somewhere in between C and Java on this
issue. It tries to eliminate as many of these non-portable behaviors as
possible without significantly affecting power or performance. (One that
can't be eliminated is the size in bytes of a pointer, sigh.)

-Walter
www.digitalmars.com/d/ the D Programming Language
 
C

Chris Croughton

Sometimes people misattribute the portability of Java to the fact that it
runs on a virtual machine. It isn't true,

Correct, the truth is that Java is not portable, not even to the next
version of the SDK in many cases (and try getting Sun code to run on
someone else's JVM). This is likely to be true of any language which is
specified only by a single owner, they can (and do) change the
specification whenever they feel like it.

Contrast with the fuss when a couple of new keywords are suggested for
C, or a deprecated feature is removed.
the real reason that Java code is
portable is the language designers made a major effort to eliminate
implementation defined, undefined, and unspecified behavior.

Hah! Try telling that to any of the Java programmers I know.
Much of the implementation defined, etc., behaviors of C are legacies left
over from how early implementations differed. Some of it is from trying to
improve efficiency on some CPUs, such as whether char's are signed or not.
Portability of C code is achieved by carefully avoiding such things, and one
really has to know C well to do it successfully.

The signedness of char is one of the biggest mistakes in the language.
They should have been defined as unsigned from the start (there's no
reason something that small needs to be signed) and avoided all of the
hassles with extended character sets (and EBCDIC).
Perhaps the time has come for C (and C++) to make a pass through the
standard and take a hard look at each of these and get rid of as many as
possible. Getting rid of the order-of-evaluation problems of expressions is
probably a good start. The implementation signed-ness of chars is another
one. I don't believe the efficiency reasons for these being implementation
defined are valid any longer.

I don't believe there ever were efficiency reasons for the signedness of
chars.
The D programming language falls somewhere in between C and Java on this
issue. It tries to eliminate as many of these non-portable behaviors as
possible without significantly affecting power or performance. (One that
can't be eliminated is the size in bytes of a pointer, sigh.)

But is there an agreed specification? Are there compilers for all
platforms?

Chris C
 
R

Richard Bos

That's the philosophy of the C-like language known as "D"
(www.digitalmars.com). The stated idea of that language is that things
should be either right or wrong (not the endless shades of grey that is
the situation in C) and that the compiler is able to tell right from wrong.

Then the people at Digitalmars know no more of Turing-completenes than
our macro freak does. Nor of the halting problem.

Richard
 
W

Walter

Chris Croughton said:
Hah! Try telling that to any of the Java programmers I know.

Java has a design goal of 100% portability, but in reality falls a bit short
of that. But it is far more portable than C is.
The signedness of char is one of the biggest mistakes in the language.

They should have been defined as unsigned from the start (there's no
reason something that small needs to be signed) and avoided all of the
hassles with extended character sets (and EBCDIC).

I agree that now it should be unsigned (and that is what D does). But early
C had to run on machines where it did make a significant performance
difference.
But is there an agreed specification?

Is there an ISO, ANSI, or ECMA standard specification? No. The specification
is at www.digitalmars.com/d/. Whether you agree with it or not is up to you
Are there compilers for all platforms?

All? No. But there are compilers for Win32, Linux, Mac OS X, FreeBSD, and
Cygwin. Since it's been integrated with gcc, a compiler for any platform
that gcc supports is within reach of any interested party.

-Walter
www.digitalmars.com C, C++, D compilers
"code of the nerds"
 
L

Lawrence Kirby

On Sat, 12 Feb 2005 16:48:44 +0000, RoSsIaCrIiLoIA wrote:

....
if someone write *s=++*s; and this is your "undefined behaviour"
compiler has not compile...

That could be detected by a compiler. The problem is an expression like
*s=++*t; which fails when s==t, i.e. they point to the same object. This
isn't generally decidable at sompile time so the C standard can't place a
requitement on a compiler to detect it. You are right that the C language
could give a well defined behaviour in that respect but there are
potential efficiency issues with thst aspproach. It is a design decision,
if you prefer another approach, you'll need to find another language that
implements it.

Lawrence
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top