For Programmers: Free Programming Magazines  


Home > Archive > Fortran > March 2006 > Illegal internal write?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Illegal internal write?
John Harper

2006-02-27, 7:05 pm

The f95 standard 9.4.4.4, and the f2003 standard 9.5.3.4, both say:

"If an internal file has been specified, an input/output list item
shall not be in the file or associated with the file."

In the WRITE statement in the following program, the input/output
list item is IMHO not in the file, but it is an expression whose
value depends on that of the file. Does that make it "associated"
as that term is used in those Fortran standards?

PROGRAM testnoforall
CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
WRITE(fmts,'(A)')("(1X,A,"//trim(fmts(i))//")", i=1,3)
PRINT "(A)",fmts
END PROGRAM testnoforall

Five f95 compilers that I tried accepted the program at compile time.
At run time, four of them printed
(1X,A,I0)
(1X,A,ES11.4)
(1X,A,F8.4)
as I had hoped. However, one (gfortran) printed
(1X,A,) (1X,A,) (1X,A,)

The quoted rule is not in a Constraint, so I can't complain if
a program defying it compiles and runs, but if the program is
standard-conforming, which output is correct?

--
John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
robert.corbett@sun.com

2006-02-28, 3:58 am

John Harper wrote:

> The f95 standard 9.4.4.4, and the f2003 standard 9.5.3.4, both say:
>
> "If an internal file has been specified, an input/output list item
> shall not be in the file or associated with the file."
>
> In the WRITE statement in the following program, the input/output
> list item is IMHO not in the file, but it is an expression whose
> value depends on that of the file. Does that make it "associated"
> as that term is used in those Fortran standards?


Association holds between entities (see Section 16.4 of the
Fortran 2003 standard). The expression you show is not an
entity, so association does not apply. I suspect the intent was
to say that no entity referenced in an input/output list item shall
be in the file or associated with the file, but the standard doesn't
say that

I thought that the statement

The evaluation of a function reference shall neither affect nor
be affected by the evaluation of any other entity in the
statement.

in Section 7.1.8 of the Fortran 2003 standard might cover this
case, but I no longer think so.

What happens if you reverse the order of the implied DO-loop
(have it go from three to one by steps of minus one)?

> PROGRAM testnoforall
> CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
> WRITE(fmts,'(A)')("(1X,A,"//trim(fmts(i))//")", i=1,3)
> PRINT "(A)",fmts
> END PROGRAM testnoforall
>
> Five f95 compilers that I tried accepted the program at compile time.
> At run time, four of them printed
> (1X,A,I0)
> (1X,A,ES11.4)
> (1X,A,F8.4)
> as I had hoped. However, one (gfortran) printed
> (1X,A,) (1X,A,) (1X,A,)


Did it print the three formats all on one line as shown?

> The quoted rule is not in a Constraint, so I can't complain if
> a program defying it compiles and runs, but if the program is
> standard-conforming, which output is correct?


Bob Corbett

glen herrmannsfeldt

2006-02-28, 3:58 am

John Harper wrote:

(snip)

> PROGRAM testnoforall
> CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
> WRITE(fmts,'(A)')("(1X,A,"//trim(fmts(i))//")", i=1,3)
> PRINT "(A)",fmts
> END PROGRAM testnoforall


Multirecord internal I/O is so rare, I almost didn't see what it was
doing. When I read it earlier I thought you might be modifying the
format string.

> Five f95 compilers that I tried accepted the program at compile time.
> At run time, four of them printed
> (1X,A,I0)
> (1X,A,ES11.4)
> (1X,A,F8.4)
> as I had hoped. However, one (gfortran) printed
> (1X,A,) (1X,A,) (1X,A,)


I remember a story about WATFIV having different results from other
compilers in the case of overlapping writes using T format. As well as
I know, it initialized the whole output buffer to blanks (it uses fixed
length output records) and then only copies non-blanks to the buffer.

Something like (I9,T1,I9) writing a large small number over a large, it
wouldn't completely overwrite it. It seems that gfortran is
initializing the output to blanks before doing the specified operation.
As far as I know, that is legal.

-- glen

Richard Maine

2006-03-01, 3:57 am

John Harper <harper@mcs.vuw.ac.nz> wrote:

> In article <1141101391.924535.83980@v46g2000cwv.googlegroups.com>,
> <robert.corbett@sun.com> wrote:
>
> Agreed. Shouldn't the f2008 standard tidy up this point?


Yes, assuming that it isn't already covered elsewhere. There certainly
is no association of relevance involved here. I'm (reasonably) confident
that the intent is to disallow any cross-effects like this. I'd have to
go drag out the standard and do some reading to see whether I thought
there was already a prohibition of this case buried in one of the other
conditions. If there isn't, I'd not only think it appropriate for f2008,
I'd also think it merited an interp to fix it in f2003.

After all, this would be (assuming it isn't already covered) an
incompatible change in f2008 if one took the attitude that it was legit
in f2003, but to be disallowed in f2008. Further, if one really expected
f2003 compilers to get this "right" (for a suitable definition of
"right"), then I wouldn't see much benefit to disallowing it in f2008.
The point of disalllowing it would be to avoid having to force compilers
to go through extra complication for something of such minimal utility,
and also to avoid having to define what it meant if that isn't clear
already (though if it isn't clear already, that woudl be a subtle
argument for it being disallowed - the standard does say that code has
to have an interpretation established by the standard in order to be
standard-conforming; we normally prefer to make prohibitions more
explicit, but there is that "back pocket" one.)

Perhaps I'll look at this more carefully in a day or two. Home with a
cold the last two days and I don't really feel like studying carefully
enough to check this carefully right now.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
glen herrmannsfeldt

2006-03-01, 3:57 am

John Harper <harper@mcs.vuw.ac.nz> wrote:

> On also changing the WRITE statement in PROGRAM testnoforall3 to
> WRITE(fmts(3:1:-1),"(A)")("(1X,A,"//trim(fmts(i))//")", i=3,1,-1)
> gfortran crashed, and g95, Sun, NAG, and Compaq f95 all printed
> '(1X,A,I0) '
> '(1X,A,ES11.4) '
> '(1X,A,F8.4) '


It would be interesting to see the result with only only loop
going backwards, though maybe not useful for your problem.

> The moral appears to be that if your compiler objects to
> FORALL(i = 1:3) fmts(i) = "(1X,A,"//trim(fmts(i))//")"
> (some do, in my experience), then the best workaround is to replace
> that by a conventional DO loop, not by an internal write to the same
> array. Attempting the latter seems to be allowed by what the f95 and
> f2003 standards say, but not by what they should have said.


I have seen many C programs do something like:

sprintf(str,"%s %d",str,i); to append, ... sort of like:

WRITE(STR,'(A,1X,I0)') TRIM(STR),I

which I am pretty sure (the C code) is non-standard C. Note especially the
effect due to null terminated strings. It seems to work most
of the time, though.

-- glen
John Harper

2006-03-01, 3:57 am

In article <du2rml$t83$2@naig.caltech.edu>,
glen herrmannsfeldt <gah@seniti.ugcs.caltech.edu> wrote:
>John Harper <harper@mcs.vuw.ac.nz> wrote:
>
>
>It would be interesting to see the result with only only loop
>going backwards, though maybe not useful for your problem.


My previous postings dealt with 3 of the possible 4 cases, as each of
the two implied loops in its internal WRITE statement may go either
forwards or backwards. I assume that Glen's "only only" implies
curiosity about the fourth case, so here it is. This program:

PROGRAM testnoforall5
CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
WRITE(fmts(3:1:-1),"(A)")("(1X,A,"//trim(fmts(i))//")", i=1,3)
PRINT "(A)","'"//fmts//"'"
END PROGRAM testnoforall5

gave this output with g95, NAG and Sun f95:
'(1X,A,(1X,A,I0)) '
'(1X,A,ES11.4) '
'(1X,A,I0) '
but this with Compaq f95:
'(1X,A,F8.4) '
'(1X,A,ES11.4) '
'(1X,A,I0) '
It made gfortran crash at compile time; the version I was using was
GNU F95 version 4.0.3 20060212 (prerelease) (Debian 4.0.2-9)
(i486-linux-gnu) compiled by GNU C version 4.0.3 20060212 (prerelease)

Glen was kind enough to wonder about my original problem. That was to
generate several formats at run-time in the most efficient way. As that
has now led to 5 versions of the program (you haven't seen the one with
an ordinary DO loop as it caused no trouble) on 5 different compilers,
which live on 3 different machines here, and made me post to c.l.f 3
times, having hunted in both the f95 and f2003 standards, my net
efficiency is perilously near tiny(0d0) :-) I didn't start by thinking
the standard should forbid something it should never have allowed!

--
John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
robert.corbett@sun.com

2006-03-01, 3:57 am


John Harper wrote:
> In article <1141101391.924535.83980@v46g2000cwv.googlegroups.com>,
> <robert.corbett@sun.com> wrote:
>
> Agreed. Shouldn't the f2008 standard tidy up this point?
>
>
> Bob asked two questions, which I answer in reverse order.
>
> 1. Yes. To clarify the "all on one line" problem I changed the program
> to print an apostrophe at each end of fmts(i), with
> PRINT "(A)","'"//fmts//"'"
> gfortran then printed
> '(1X,A,) (1X,A,) (1X,A,) '
> ' '
> ' '


Zooks! I am flabbergasted by that output. I thought I understood what
gfortran was doing, but now I know I don't.

> 2. On also changing the program to reverse the implied DO-loop, i.e.
>
> PROGRAM testnoforall3
> CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
> WRITE(fmts,"(A)")("(1X,A,"//trim(fmts(i))//")", i=3,1,-1)
> PRINT "(A)","'"//fmts//"'"
> END PROGRAM testnoforall3
>
> gfortran printed the following, which I cannot explain:
> '(1X,A,) (1X,A,) (1X,A,(1'
> 'X,A,) (1X,A,)) '
> ' '
> g95, Sun and NAG f95 printed this, which I also cannot explain:
> '(1X,A,F8.4) '
> '(1X,A,ES11.4) '
> '(1X,A,(1X,A,F8.4)) '


I was expecting something like this.

Bob Corbett

glen herrmannsfeldt

2006-03-01, 3:57 am

robert.corbett@sun.com wrote:
> John Harper wrote:


(snip)


(snip)
[color=darkred]
[color=darkred]
> Zooks! I am flabbergasted by that output. I thought I understood what
> gfortran was doing, but now I know I don't.


I don't think I understand at all how trim() is actually implemented,
which is pretty important for a case like this. Consider one that moves
one character at a time. First copy "(1X,A," into the destination.
Now look at trim(fmts(1)), it contains "(1X,A, ",
trim it and copy it. I would then expect:

"(1X,A,(1X,A,) "

I would probably test gfortran with an ordinary multi-record internal
write to see it it does that right.


I tried in C:

#include <stdio.h>
int main() {
char buf[1000];
strcpy(buf,"I0");
sprintf(buf,"(1X,A,%s)",buf);
printf("%s\n",buf);
}

and got:

(1X,A,(1)

which surprised me.

I thought it would keep writing off the end of the buffer.

-- glen

John Harper

2006-03-01, 9:57 pm

In article <du4ue8$j30$2@naig.caltech.edu>,
glen herrmannsfeldt <gah@seniti.ugcs.caltech.edu> wrote:
>Steven G. Kargl <kargl@troutmask.apl.washington.edu> wrote:
>
>I was expecting that it would get ordinary multi-record internal
>write wrong, too. I couldn't think of one that would do what his
>was doing that would normally get it right. Maybe he will try
>that, too.
>
>As far as I know, multi-record is rarely used.


My program had two problematical features
(1) multi-record internal write
(2) the same character array in an expression in an output
list and as an internal file.
This program avoids (2) by using two character arrays f and fmts:

PROGRAM testintwrite
CHARACTER(24) :: f(3) = (/"I0 ","ES11.4","F8.4 "/),fmts(3)
WRITE(fmts,"(A)")("(1X,A,"//trim(f(i))//")", i=1,3)
PRINT "(A)","'"//fmts//"'"
END PROGRAM testintwrite

G95 and Sun, Compaq and NAG f95 all compiled that and printed
'(1X,A,I0) '
'(1X,A,ES11.4) '
'(1X,A,F8.4) '
My "ancient" gfortran compiled it but printed
'(1X,A,I0) (1X,A,ES11.4) '
'(1X,A,F8.4) '
' '
but when I asked our systems man to update it the reply was
We would only upgrade the existing package from within Debian,
it is currently 4.0. If the debian team backport a patch it will
get updated with the next OS update.
So I can't yet check what the latest gfortran does with that program
myself:-( Would anyone else like to?

--
John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Steven G. Kargl

2006-03-01, 9:57 pm

In article <1141252648.173949@bats.mcs.vuw.ac.nz>,
harper@mcs.vuw.ac.nz (John Harper) writes:
> In article <du4ue8$j30$2@naig.caltech.edu>,
> glen herrmannsfeldt <gah@seniti.ugcs.caltech.edu> wrote:
>
> My program had two problematical features
> (1) multi-record internal write
> (2) the same character array in an expression in an output
> list and as an internal file.
> This program avoids (2) by using two character arrays f and fmts:
>
> PROGRAM testintwrite
> CHARACTER(24) :: f(3) = (/"I0 ","ES11.4","F8.4 "/),fmts(3)
> WRITE(fmts,"(A)")("(1X,A,"//trim(f(i))//")", i=1,3)
> PRINT "(A)","'"//fmts//"'"
> END PROGRAM testintwrite
>
> G95 and Sun, Compaq and NAG f95 all compiled that and printed
> '(1X,A,I0) '
> '(1X,A,ES11.4) '
> '(1X,A,F8.4) '
> My "ancient" gfortran compiled it but printed
> '(1X,A,I0) (1X,A,ES11.4) '
> '(1X,A,F8.4) '
> ' '
> but when I asked our systems man to update it the reply was
> We would only upgrade the existing package from within Debian,
> it is currently 4.0. If the debian team backport a patch it will
> get updated with the next OS update.


Ugh! John, save yourself some hair pulling and stop using gfortran
if all you have is 4.0. GCC 4.1 was released yesterday. Hopefully,
Debian will upgrade ASAP.

> So I can't yet check what the latest gfortran does with that program
> myself:-( Would anyone else like to?


gfortran 4.1
troutmask:sgk[205] gfc41 -o z harp3.f90
troutmask:sgk[206] ./z
'(1X,A,I0) '
'(1X,A,ES11.4) '
'(1X,A,F8.4) '

gfortran from trunk (bleeding edge)
troutmask:sgk[207] gfc4x -o z harp3.f90
troutmask:sgk[208] ./z
'(1X,A,I0) '
'(1X,A,ES11.4) '
'(1X,A,F8.4) '

--
Steve
http://troutmask.apl.washington.edu/~kargl/
James Giles

2006-03-01, 9:57 pm

Richard Maine wrote:
> glen herrmannsfeldt <gah@seniti.ugcs.caltech.edu> wrote:
>
>
> I suppose it depends both on your sample set and on your definition of
> "rarely". I've certainly both seen and used it a fair number of
> times. I don't consider it particularly rare or obscure. It certainly
> isn't as common as single-record internal I/O; that statement seems
> safe.


I have no idea of how many people use multi-record internal
files. The percentage is certainly limited by the fact that a
number of people are unaware that they're possible.

There is some confusion on that point because of the way
format specifiers in I/O work: an array of strings used as a
format is treated as if it were a single string consisting of all
the array elements concatenated together in array element order.
Some people assume that internal files are treated the same
way (an array would be one long record). I know some people
assume that, because I've had to correct people that said so.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies." -- C. A. R. Hoare


Richard E Maine

2006-03-02, 7:00 pm

I previously suggested that I'd look at this a little more when I got
back to work. Did so.

John Harper <harper@mcs.vuw.ac.nz> wrote:

> PROGRAM testnoforall
> CHARACTER :: fmts(3)*24 = (/"I0 ","ES11.4","F8.4 "/)
> WRITE(fmts,'(A)')("(1X,A,"//trim(fmts(i))//")", i=1,3)
> PRINT "(A)",fmts
> END PROGRAM testnoforall


Ok. I found the stuff I was thinking about, but this one doesn't seeem
to be there. In 9.11, which is "hiding" at the end of the chapter. The
6th para is

"The value of a specifier in an input/output statement shall not
depend on any input-item,... [or just about anything in sight]".

That's nice and general and covers an awful lot of "sins", but not this
one because an i/o-list-item isn't a specifier. What I think we ought to
have is a similarly broad one saying that an I/O list item can't depend
on any "output specifier" (except that I don't think we have a word for
"output specifier", so we either have to make such a word, say iot in
longhand, or list them). You really do want it pretty broad like that.
If you write something specific to internal units, the next strange case
someone will ask about would involve the errmsg specifier or some such
thing.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Dave Thompson

2006-03-05, 9:57 pm

On Tue, 28 Feb 2006 22:03:09 -0800, glen herrmannsfeldt
<gah@ugcs.caltech.edu> wrote:

<snip: internal write to buffer also used in an output item>
> I tried in C:
>
> #include <stdio.h>
> int main() {
> char buf[1000];
> strcpy(buf,"I0");
> sprintf(buf,"(1X,A,%s)",buf);
> printf("%s\n",buf);
> }
>

Note that isn't supported by the C standard; 7.19.6.6p2 "If copying
takes place between objects that overlap, the behavior is undefined."
and similarly .5,12,13.

(Aside: you also need <string.h> for strcpy.)

> and got:
>
> (1X,A,(1)
>
> which surprised me.
>
> I thought it would keep writing off the end of the buffer.
>

I am too. Apparently it presaved the length at call. I would be less
surprised by length saved at access i.e. (1X,A,(1X,A,) . If one has
(had) unlimited spare time, it might be interesting to look at your
implementation if it is one that permits it i.e. not IP-restricted.
Although of course Undefined Behavior _permits_ anything.

- David.Thompson1 at worldnet.att.net
Gary L. Scott

2006-03-05, 9:57 pm

Dave Thompson wrote:
> On Tue, 28 Feb 2006 22:03:09 -0800, glen herrmannsfeldt
> <gah@ugcs.caltech.edu> wrote:
>
> <snip: internal write to buffer also used in an output item>
>
>
> Note that isn't supported by the C standard; 7.19.6.6p2 "If copying
> takes place between objects that overlap, the behavior is undefined."
> and similarly .5,12,13.
>
> (Aside: you also need <string.h> for strcpy.)


Such an antiquated method of importing procedures...looks like something
invented in the 70's. String handling is pretty basic. It should be
assumed (as are IO and math).

>
>
>
> I am too. Apparently it presaved the length at call. I would be less
> surprised by length saved at access i.e. (1X,A,(1X,A,) . If one has
> (had) unlimited spare time, it might be interesting to look at your
> implementation if it is one that permits it i.e. not IP-restricted.
> Although of course Undefined Behavior _permits_ anything.
>
> - David.Thompson1 at worldnet.att.net



--

Gary Scott
mailto:garyscott@ev1.net

Fortran Library: http://www.fortranlib.com

Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html

Why are there two? God only knows.


If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford
glen herrmannsfeldt

2006-03-06, 3:57 am

Dave Thompson wrote:
> On Tue, 28 Feb 2006 22:03:09 -0800, glen herrmannsfeldt


(snip)

[color=darkred]
> Note that isn't supported by the C standard; 7.19.6.6p2 "If copying
> takes place between objects that overlap, the behavior is undefined."
> and similarly .5,12,13.


That was the reason to try it. I have seen fairly often sprintf where
the first item is also the result buffer, which seems to work much of
the time, but I don't do that.

> (Aside: you also need <string.h> for strcpy.)


Technically, that is true. On the other hand, it seems to
work without it. For non-varargs routines not requiring any
conversions it is likely to work, and even varargs have a good chance
to work.

I ran it on FreeBSD with GCC 2.7.2.3.

-- glen

Richard Maine

2006-03-06, 3:57 am

glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:

> Dave Thompson wrote:


>
> Technically, that is true. On the other hand, it seems to
> work without it.


Just like many nonstandard things can happen to work in many contexts.
"It seems to work" is not a very good criterion for professional work.
Have you verified that it works on all compilers in all cases? That's a
rhetorical question, of course.

There are also many nonstandard things in Fortran that "seem to work"...
that is, until they don't.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
glen herrmannsfeldt

2006-03-06, 3:57 am

Richard Maine wrote:

> glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:


[color=darkred]
[color=darkred]
[color=darkred]
> Just like many nonstandard things can happen to work in many contexts.
> "It seems to work" is not a very good criterion for professional work.
> Have you verified that it works on all compilers in all cases? That's a
> rhetorical question, of course.


Well, the standard does say what happens if there is no prototype in
scope, which is necessary for pre-ANSI compatibility.

> There are also many nonstandard things in Fortran that "seem to work"...
> that is, until they don't.


It is similar, as far as I can tell, to not having an INTERFACE when
no newer than F77 features are being used.
Calling strcpy with parameters that are not (char*), such as (unsigned
char*), would require the prototype.

A reference to sqrt(2) should fail without #include <math.h>, as sqrt
expects a double. Anything with a (FILE*) argument pretty much requires
the #include file that defines (FILE*).

-- glen

Dave Thompson

2006-03-19, 9:56 pm

On Sun, 05 Mar 2006 23:00:33 -0800, glen herrmannsfeldt
<gah@ugcs.caltech.edu> wrote:

> Richard Maine wrote:
>
>
>
>
>
>
> Well, the standard does say what happens if there is no prototype in
> scope, which is necessary for pre-ANSI compatibility.
>

If no declaration is in scope, the C89/90 standard says that the
function is implicitly declared to return int and take unspecified
K&R1-compatible arguments. Technically it is Undefined Behavior to
call a function returning char* as if it returned int, although on
most if not all systems it does work, especially if you don't (try to)
use the returned value, as here IIRC. C99 deletes the implicit
declaration feature, and requires a diagnostic, after which a C99
implementation is likely to implement the C89 way for compatibility.

>
> It is similar, as far as I can tell, to not having an INTERFACE when
> no newer than F77 features are being used.


I think it is -- both in the feature itself, and the reason it is
there. Which provides us (me?) with a tenuous link back to topic.

> Calling strcpy with parameters that are not (char*), such as (unsigned
> char*), would require the prototype.
>

Actually, that one wouldn't. Although in C's type system char * and
unsigned char *, and for that matter char * and const char *, are not
formally 'compatible', they are required to have the same
representation; in C89/90 this is nonnormatively 'intended' to allow
interchangeability as unprototyped arguments among other things; in
C99 this is explicit 6.5.2.2p6 and 7.15.1.1p2 for the similar varargs
case. Signed versus unsigned integers of the same 'rank' (informally,
size) have the same special dispensation for nonnegative values.

> A reference to sqrt(2) should fail without #include <math.h>, as sqrt
> expects a double. Anything with a (FILE*) argument pretty much requires
> the #include file that defines (FILE*).
>

To be contrarian, you _could_ have a machine where int is a subset of
and shares the representation of double, and then the implicit wrong
declaration of sqrt() would actually work. But that's damn rare.

OTOH, FILE in practice almost always is a struct, although not
formally required to be, and all struct pointers must have the same
representation, so you can probably get away with "struct fakefile *".
OT3H, why bother? It's easier as well as safer to #include <stdio.h>.\


- David.Thompson1 at worldnet.att.net
glen herrmannsfeldt

2006-03-21, 3:57 am

Dave Thompson wrote:
(snip)

> If no declaration is in scope, the C89/90 standard says that the
> function is implicitly declared to return int and take unspecified
> K&R1-compatible arguments. Technically it is Undefined Behavior to
> call a function returning char* as if it returned int, although on
> most if not all systems it does work, especially if you don't (try to)
> use the returned value, as here IIRC. C99 deletes the implicit
> declaration feature, and requires a diagnostic, after which a C99
> implementation is likely to implement the C89 way for compatibility.


Most implementations that I know of return small results in registers,
so ignoring them usually works. This might be slightly more of a
problem in Fortran than C. As I understand it, though I never tried it,
some early C programs that expected a (char*), and then returned it
unmodified to their caller would declare both as int. I never wrote any
that way, though.

(snip, I wrote)

[color=darkred]
> I think it is -- both in the feature itself, and the reason it is
> there. Which provides us (me?) with a tenuous link back to topic.


(snip)

[color=darkred]
> To be contrarian, you _could_ have a machine where int is a subset of
> and shares the representation of double, and then the implicit wrong
> declaration of sqrt() would actually work. But that's damn rare.


There was a discussion somewhere, maybe here, about some machines like
that, maybe CDC and/or Burroughs. Normalization for floating point
prefers a zero exponent, and the position of the binary point is such
that values with zero exponent have the same bit representation as an
integer. (Likely ones complement in the CDC case.)

It would still fail, though, if the return value from sqrt() wasn't an
integer.

Closer to Fortran, the IBM 704 uses 36 bits for REAL, but only 16 for
INTEGER in the same sized register and, if it follows Fortran tradition,
in memory. The five digit statement numbers were originally only up to
32767, the 99999 limit came later. (How many programs ever needed more
than 32767?)



(snip)

-- glen

John Harper

2006-03-21, 10:05 pm

In article < LNadnTKnwPrFVILZnZ2dnUVZ_vmdnZ2d@comcast
.com>,
glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
>
>
>There was a discussion somewhere, maybe here, about some machines like
>that, maybe CDC and/or Burroughs.


Certainly Burroughs worked that way. It was a nuisance because it
prevented the compiler detecting the error when one of the dummy and
actual arguments of a procedure was real and the other was integer.

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com