HDTenEightyP/NetNews huggingface dataset:
From: dsb@duke.cs.duke.edu (D. Scott Bigham)
Newsgroups: comp.std.c,comp.lang.c
Subject: Re: Scientists as Programmers (was Re: Small Language Wanted)
Date: 16 Sep 92 04:15:18 GMT
Followup-To: comp.std.c
Organization: n. Arrangement in an orderly or logical fashion.  See "miracle".

From the Holy Book of <1992Sep16.014635.27449@nntpd.lkg.dec.com>
  as spake by diamond@jit.dec.com (Norman Diamond) :
>Yeah, and Mr. Bigham tried to trick me into posting to comp.lang.c (without
>warning), so I've added comp.lang.c back in for Mr. Bigham.

Trick?  My dear sir, that's where I _found_ the article I was replying
to!  Follow-ups re-redirected for your peace of mind. :)

>OK, I can find in ANSI 3.2.1.5, page 36 lines 17 to 18, "and yield result
>types in a similar way.  The purpose is to yield a common type, which is
>also the type of the result."

However (I take you to mean), if the product overflows the type of the
result, we experience the dreaded Undefined Behavior and the compiler is
free to do anything it wants, including changing the type of the result
to accommodate the value of the product.  Okay, fair enough.

>Sounds like it agrees with the standard.  Sometimes the result [of cast
>to int] is defined by the standard, the rest of the time the result is
>defined by the implementation, and the result is never undefined.

A fine distinction, and one I'm not certain I understand.  Is the
implementation required, for instance, to inform the programmer how it
will behave in an "implementation-defined" situation?  Is the
implementation free to define that overflow in expressions causes your
computer to turn into an alligator?

						-sbigham
-- 
Scott Bigham                   | The opinions expressed above are
dsb@romeo.cs.duke.edu          | (c) 1992 Hacker Ltd. and cannot be
bigham@hercules.acpub.duke.edu | copied or distributed without a
    (but not for long)         | Darn Good Reason(tm).
Newsgroups: comp.std.c
From: gordon@sneaky.lonestar.org (Gordon Burditt)
Subject: Re: Operations on Files
Keywords: ANSI C, files
Organization: Gordon Burditt
Date: Fri, 4 Sep 1992 10:05:22 GMT

>	The ANSI C standard seems to have a rather odd mix of file 
>operations.  Why didn't they add (over K&R) some other useful file 
>operations such as fileexist, getfirst, getnext, etc?  It seems that 
>these could not be much more dependent on the underlying file system than 
>rename or remove.

It is not the job of standards committees to invent a lot of new
functions.  There have been many complaints that the committee went
too far with inventing things already.

Adding directory-reading interfaces to ANSI C brings up many issues which
ANSI C would be better off trying not to nail down.  

A getfirst/getnext interface (which I assume refers to the CP/M
directory-reading calls which later made their way into MSDOS)
is irritating, because of the contortions needed to loop over all
files, treating the first call specially.  One of the really
irritating problems in CP/M, which may have made its way into MSDOS,
is that there was no documented way to get or restore the "next directory 
entry pointer" (except to the beginning), and further, other file 
operations like creating, deleting, or opening files messed up that
hidden variable.

But there's a worse problem.  What do the terms "first" and "next" 
mean, given that the program is doing things to the directory during 
a scan?  Even an opendir()/readdir()/closedir() interface has
this problem.

What should the following loop do?  Assume you've got a function
called readdirname() which returns the names (strings) of files
in a directory on successive calls, and returns NULL when it
reaches the end.

	char	*fn;

	opendirname(name);
	while ((fn = readdirname()) != NULL)
		remove(fn);

Does this delete ALL the files?  That assumes that the directory stays
in the same order (except for the file being deleted) during a
remove().  Directories that are maintained sorted, use hashing, or
do automatic compaction either make it impossible to implement
readddirname() on top of the existing OS, or end up skipping files.
Some versions of VMS, at least, had some problems with this. 
The issue gets even more confusing if you throw in another process
that repeatedly creates and deletes "x.tmp".  Does this cause the
loop above to skip some entries OTHER THAN "x.tmp"?

					Gordon L. Burditt
					sneaky.lonestar.org!gordon
Newsgroups: comp.std.c
From: flaps@dgp.toronto.edu (Alan J Rosenthal)
Subject: Re: struct hack, and other out-of-array references
Date: 12 Sep 92 20:46:48 GMT

fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>Do same considerations would apply if you tried to use a char[5][5] 
>array as a char[25] array?

Actually, I don't think that they do, because along the path to doing this
screwing around you go through a (char *).

>From what you're saying, the reason that casting the return
>value from malloc succeeds is only because malloc is "magic".

I think the magic of pointer-to-char comes into play too.  Any object can be
traversed by pointers-to-char.  So in your example, in my opinion, you're ok
because the dubious operation occurs with pointers-to-char.

Note that you're even guaranteed that the "sizeof" of a char[5][5] array is
exactly 25, because sizeof(char) has to be 1 and an array 5 of something has to
be exactly 5 times the "sizeof".
Newsgroups: comp.std.c
From: flaps@dgp.toronto.edu (Alan J Rosenthal)
Subject: Re: struct hack, and other out-of-array references
Date: 11 Sep 92 05:24:38 GMT

dat@thinkage.on.ca (David Adrien Tanguay) writes:
>How is this any different from the array example?  p may point
>outside a[1], but it is still within the a object.  Similarly, ...
>is outside the f->s object but within the malloc object.

The point is, "int a[5][5];" doesn't give you 25 ints, it gives you five arrays
of five ints each.  "(int(*)[5])malloc(5*sizeof(int[5]))" gives you
sizeof(int)*25 bytes which are ALSO five arrays of five ints.

The first looks like this:
	int[5][5]:
	    int[5]:
		int
		int
		int
		int
		int
	    int[5]:
		...
	    ...

And the second looks like this:
	char
	char
	char
	char
	...

Now that cast magically makes the second be close enough to the first in
outward appearance for all intents and purposes, but it's still the second
underneath.  Obviously in almost all compilers the memory layout will be the
same.  However, an environment such as Saber-C should be free to keep track of
the details and that's why I've always thought that this is a good
interpretation ruling.

I'm not sure what you get when you take a pointer to that array five of array
five of int, cast it to a (char *), then cast it to a (int(*)[5]).
From: karl@ima.isc.com (Karl Heuer)
Newsgroups: comp.std.c
Subject: Re: Change to time() fn?
Date: 13 Sep 92 18:45:30 GMT
Organization: Interactive Systems, Cambridge, MA 02138-5302

In article <1992Sep12.140423.23672@iqsc.COM> matt@iqsc.COM (Matt Reedy) writes:
>And you're right, the number of seconds from that point to today is roughly
>60*60*24*365*92 which is 2.9 billion.
>
>The interesting thing about Microsoft's doc is that their example program
>calls this function, and does a printf("The number of seconds since 1/1/70:").
>So, which one is right, the comment or the sample program???

Assuming they implemented time_t as a signed 32-bit integer, didn't you just
finish agreeing with me that the documentation *cannot* be correct?

Of course, if you have access to this implementation, you could run the
sample program and do the arithmetic on the output value, and verify that
it does correspond to the 1970 Epoch.  My guess is that someone in charge
of documentation decided that an American audience would have trouble
understanding "00:00" and so attempted to change it to "midnight" (meaning
24:00) of the previous day; and this person managed to get 1899 when
subtracting one from 1970.  (Possibly through a typo, or by blindly assuming
that the "1970" in the original *must* have been a typo for 1900.)

Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
From: clive@x.co.uk (Clive Feather)
Newsgroups: comp.std.c
Subject: Re: space optimization involving enum
Date: 7 Sep 92 10:31:32 GMT
Organization: IXI Limited, Cambridge, UK

In article <1992Aug29.232155.14657@sq.sq.com> msb@sq.sq.com (Mark Brader) writes:
>>> ... The representation of [decimal] 10000 has to use the bit
>>> sequence 10011100010000.  
>> As I read it, wrong.  Nothing I see prevents use of 2's complement, 
>> 1's complement, or excess-2**(n-1) (the sign bit being reversed from
>> 2's complement).
> These systems are indeed all permissible.  But they also all use the
> bit sequence 10011100010000 in the representation of decimal 10000.

Both wrong. Excess-2**(n-1) is not a permitted system, because the
representation of decimal 10000 is not binary 10011100010000. The
standard requires that the representation of integers be a "pure-binary"
system, except for the sign bit, and that unsigned and signed integers
use the same representation for numbers where their ranges overlap.

-- 
Clive D.W. Feather     | IXI Limited         | If you lie to the compiler,
clive@x.co.uk          | 62-74 Burleigh St.  | it will get its revenge.
Phone: +44 223 462 131 | Cambridge   CB1 1OJ |   - Henry Spencer
Fax:   +44 223 462 132 | United Kingdom      |
Newsgroups: comp.std.c
From: karl@ima.isc.com (Karl Heuer)
Subject: Re: Memory alignment
Organization: Interactive Systems, Cambridge, MA 02138-5302
Date: Tue, 15 Sep 1992 22:57:28 GMT

In article <lbc3neINNtt@news.bbn.com> langevin@indian.bbn.com. (Tim Langevin) writes:
>   Is the following piece of code conforming ANSI C?

I believe so, but only because you didn't do anything with the pointer you
generated.  If you want it to be a general-purpose memory allocator, then it's
conceivable that it fails when you try to use it for some type not included in
your ALL_TYPES union.

>   Is there a better way to do this?

I would omit the alignment object, and change the size of the allocation
request to be (sizeof(HEADER)+ALIGN-1)/ALIGN*ALIGN + user_size, where ALIGN is
a constant that you configure appropriately on each system.  (This is how
malloc() itself is often written.)

It's fairly clean, and it's portable, even if it isn't strictly conforming.

Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
Newsgroups: comp.std.c,comp.lang.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: Scientists as Programmers (was Re: Small Language Wanted)
Followup-To: comp.std.c,comp.lang.c
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Wed, 16 Sep 1992 01:46:35 GMT

In article <a_rubin.716593540@dn66> a_rubin@dsg4.dse.beckman.com (Arthur Rubin) writes:
>In <1992Sep15.043224.27920@nntpd.lkg.dec.com> diamond@jit345.bad.jit.dec.com (Norman Diamond) writes:
>>In article <1992Sep12.164915.10734@jarvis.csri.toronto.edu> flaps@dgp.toronto.edu (Alan J Rosenthal) writes:
>>>a_rubin@dsg4.dse.beckman.com (Arthur Rubin) writes:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	int a, b;   long c;
>>>>My interpretation (from reading K&R 2) would be that c = a * b should be
>>>>equivalent to c = (int)(a * b).

>K&R 1, in the section on type conversions (2.7), states:
>    The result is of the higher type....

without quite mentioning what happens when neither operand needed promoting :-)
No problem though; there's more below.

>This implies that the result in case of overflow, although undefined, is
>an undefined int.

No.  When a result is undefined, the computer is allowed to burn itself up
and be reincarnated with a different program in its memory, in which the
declared datatypes have magically changed to "long".

(If the result were unspecified, it would be an unspecified int.  But the
standard does not say this -- likely because overflow can at least cause
your thread of execution to burn up, and maybe be reincarnated with a
change of datatype :-)

>Followups to comp.std.c, as it no longer is relevant to any of the other
>groups.

Yeah, and Mr. Bigham tried to trick me into posting to comp.lang.c (without
warning), so I've added comp.lang.c back in for Mr. Bigham.

In article <716597823@romeo.cs.duke.edu> dsb@duke.cs.duke.edu (D. Scott Bigham) writes:
>Section A7.6, "Multiplicative Operators", states that "The usual
>arithmetic conversions are performed on the operands, and predict the
>type of the result."

OK, I can find in ANSI 3.2.1.5, page 36 lines 17 to 18, "and yield result
types in a similar way.  The purpose is to yield a common type, which is
also the type of the result."  Couldn't find anything like this in the
expressions chapter though.

Oddly, the last two lines in that section (and on that page) allow
implementations to stick extra bits in floating values, without saying
anything about integral values.

>>No, cast-to-int does not overflow.  It has a defined result.

>Careful, this is _signed_ int we're talking about here.  According to
>section A6.2, "Integral Conversions", "When any integer is converted to
>a signed type, the value is unchanged if it can be represented in the
>new type and is implementation-defined otherwise."

Sounds like it agrees with the standard.  Sometimes the result is defined
by the standard, the rest of the time the result is defined by the
implementation, and the result is never undefined.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"Yeah -- bad wiring.  That was probably it.  Very bad."
Newsgroups: comp.std.c
From: karl@ima.isc.com (Karl Heuer)
Subject: Re: Change to time() fn?
Organization: Interactive Systems, Cambridge, MA 02138-5302
Date: Sat, 12 Sep 1992 04:27:47 GMT

In article <1992Sep11.194827.19500@iqsc.COM> matt@iquery.iqsc.COM (Matt Reedy) writes:
>In looking at the Microsoft C 7.0 reference manual, we noticed the
>time() function has changed its base value from 1/1/1970 to 12/31/1899.
>Is this a Posix, ANSI, or other standards body change or is it Microsoft?

ANSI doesn't specify that time() even *has* a "base value".

POSIX says that it's measured in seconds since the Epoch, but since the
number of seconds since 1899-12-31 is already more than the common value of
LONG_MAX, I doubt that they've moved the Epoch backwards like that.

Are you sure you're talking about the internal encoding of |time()|, and not
the |struct tm| representation?  (That *does* have an (unfortunate) base of
1900 for the |tm_year| component.)

Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
From: clive@x.co.uk (Clive Feather)
Newsgroups: comp.std.c
Subject: Re: struct hack
Date: 9 Sep 92 11:21:01 GMT
Organization: IXI Limited, Cambridge, UK

In article <9209080014.AA03467@enet-gw.pa.dec.com> diamond@jit081.enet.dec.com (08-Sep-1992 0914) writes:
>In article <1992Sep07.104932.20060@x.co.uk> clive@x.co.uk (Clive Feather) writes:
>>In article <9209040741.AA16120@enet-gw.pa.dec.com> diamond@jit081.enet.dec.com(04-Sep-1992 1639) writes:
>>> You can't go past the end of an array object.  But if malloc() or some other
>>> variable has defined the end of the actual array object, then the + operator
>>> can get you that far, regardless of the declared type that some other array
>>> variable had before getting flattened to a pointer.
>> But there is an intepretation that says that, given
>>    int a [5][5];
>> the access "a [1][6]" is illegal, because it goes past the bounds of the
>> array "a [1]". In other words, the declared type of the array does
>> restrict what can happen to a pointer derived from it.
> Is that an actual interpretation ruling or was that only someone's posted
> opinion on Usenet?

RFI 17, item 16.

| For an array of arrays, the permitted pointer arithmetic in Standard
| ##3.3.6 Semantics (page 48, lines 12-40) is to be understood by
| interpreting the use of the word "object" as denoting the specific
| object determined directly by the pointer's type and value, *not* other
| objects related to that one by contiguity. For example, the following
| code has undefined behaviour:
|     int a [4][5];
|     a [1][7] = 0;  /* undefined */
| Some conforming implementations may choose to diagnose an "array bounds
| violation", while others may choose to interpret such attempted accesses
| successfully with the "obvious" extended semantics.

This RFT applies to slices of arrays, but, in *my* opinion, it is
extendable to this case:

    struct fred { int i; char s [1]; } *f;
    char *s;

    /* ... */
    f = malloc (sizeof f + strlen (ss));
    if (f != NULL)
        strcpy (f->s, ss);

The pointer f->s points to an object with type "char [1]", and so, if
strlen (ss) > 0, the access to (f->s)[1] required by strlen is undefined
according to this RFI, even though the array has already decayed to a
pointer.

> I am also curious as to the "officially" correct thing to do when an
> interpretation ruling contradicts the standard (whether correcting an
> error that everyone agrees was an error, or otherwise).

You submit a new RFI asking the same question but with additional
supporting material which contradicts the original ruling.

Do you have an example ?

-- 
Clive D.W. Feather     | IXI Limited         | If you lie to the compiler,
clive@x.co.uk          | 62-74 Burleigh St.  | it will get its revenge.
Phone: +44 223 462 131 | Cambridge   CB1 1OJ |   - Henry Spencer
Fax:   +44 223 462 132 | United Kingdom      |
Newsgroups: comp.std.c
From: darcy@druid.uucp (D'Arcy J.M. Cain)
Subject: Re: calloc()
Date: Tue, 15 Sep 1992 17:30:43 GMT
Organization: D'Arcy Cain Consulting

steve@taumet.com (Steve Clamage) writes:
>darcy@druid.uucp (D'Arcy J.M. Cain) writes:
>>steve@taumet.com (Steve Clamage) writes:
>>>That said, suppose we have a system where int and size_t are 16 bits,
>>>but it is possible to allocate an object bigger than 64K.  A
>>But isn't size_t guaranteed to be big enough to specify any object?  It
>size_t is the type returned by the sizeof operator.  I believe you
>must be able to apply sizeof to any object you can declare.  Suppose

Mark Brader and I have been discussing this in email and I agree that
in the case of calloc (but not malloc) a stricly conforming compiler
might be able to allocate more bytes (but not elements) than can fit
into a size_t.  Here is an excerpt from my last message to him:

>Actually 4.10.3 never comes down on one side or the other but it does say
>that "Each allocation shall yield a pointer to an object disjoint from
>any other object."  Now of course you can't apply sizeof to the object
>because you only have a pointer to the object and hence you can only get
>the size of the pointer or the size of the first element.  However the
>discussion on sizeof does sort of imply that if you could somehow get
>an identifier for the object itself that sizeof could be applied to it
>and therefore size_t must be able to represent its size.  And of course
>if pigs had wings they might fly so I am not sure if I've proved anything
>other than that I come to these strange conclusions due to too much
>thought rather than too little.  :-)

-- 
D'Arcy J.M. Cain (darcy@druid.com)  |
D'Arcy Cain Consulting              |   There's no government
Toronto, Ontario, Canada            |   like no government!
+1 416 424 2871          DoD#0082   |
Newsgroups: comp.std.c
From: bill@twwells.com (T. William Wells)
Subject: Re: void expressions and volatile types
Date: Wed, 16 Sep 1992 00:40:51 GMT
Organization: None, Mt. Laurel, NJ

> Here's the mistake. The value of the expression can be obtained by
> remembering the value stored into a - it is not necessary to re-fetch
> it, even though a is volatile.

Wrong. The standard is quite clear: the value of the result is the
*value of the left operand after the assignment*. It is *not* the
value stored into the left operand. In the case of non-volatiles,
this makes no difference. In the case of volatiles this *requires*
an access to the variable to obtain the value.

> The storing of a value into a is a side-effect, and so takes place
> sometime before the next sequence point. Any other change that takes
> place to a (e.g. because it is a memory-mapped device) between the same
> pair of sequence points counts as a double assignment, and is therefore
> undefined, and therefore the implementation can do what it wants
> (including not reading a after storing).

Wrong again. The relevant section says *stores by an expression*
thus explicitly excluding stores from other sources.

So the question stands: does an assign to a volatile in the
context of a void expression require an additional load to obtain
the value? Or may "discard" be interpreted to mean "not obtain"?
The former requires an additional load of the volatile in order
to obtain the value; the second does not. At the moment, my
compiler does not generate the additional load because otherwise
writing device drivers would be almost impossible. But I'd really
like to see an *INFORMED* opinion on this.

---
Bill                            { uunet | decwrl | telesci }!twwells!bill
bill@twwells.com
Newsgroups: comp.std.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: Change to time() fn?
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Tue, 15 Sep 1992 04:21:20 GMT

In article <1992Sep13.184530.27370@ima.isc.com> karl@ima.isc.com (Karl Heuer) writes:
>In article <1992Sep12.140423.23672@iqsc.COM> matt@iqsc.COM (Matt Reedy) writes:
>>And you're right, the number of seconds from that point to today is roughly
>>60*60*24*365*92 which is 2.9 billion.
>>
>>The interesting thing about Microsoft's doc is that their example program
>>calls this function, and does a printf("The number of seconds since 1/1/70:").
>>So, which one is right, the comment or the sample program???
>
>Assuming they implemented time_t as a signed 32-bit integer, didn't you just
>finish agreeing with me that the documentation *cannot* be correct?

Even if they implemented time_t as a 32-bit integer, I cannot imagine why
it should be signed.  (time_t)-1 does not have to be negative, the standard
carefully recognized that, and some implementors have occasionally been
known to recognize similar opportunities for various kinds of tricks.

From the discussion that has appeared in this newsgroup, it sounds like the
documentation is *unlikely* to be correct, but it *can* be.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"Yeah -- bad wiring.  That was probably it.  Very bad."
From: matt@iqsc.COM (Matt Reedy)
Newsgroups: comp.std.c
Subject: Re: Change to time() fn?
Date: 12 Sep 92 14:04:23 GMT
Organization: IQ Software Corp.

In article <1992Sep12.042747.26773@ima.isc.com> karl@ima.isc.com (Karl Heuer) writes:
>ANSI doesn't specify that time() even *has* a "base value".
>
>POSIX says that it's measured in seconds since the Epoch, but since the
>number of seconds since 1899-12-31 is already more than the common value of
>LONG_MAX, I doubt that they've moved the Epoch backwards like that.
>
>Are you sure you're talking about the internal encoding of |time()|, and not
>the |struct tm| representation?  (That *does* have an (unfortunate) base of
>1900 for the |tm_year| component.)

Yes, it is the |time_t| value returned by |time()| that I'm looking at.
It specifically says it is the number of seconds since midnight on 
Dec 31, 1899.  And you're right, the number of seconds from that point to
today is roughly 60*60*24*365*92 which is 2.9 billion.

The interesting thing about Microsoft's doc is that their example program
calls this function, and does a printf("The number of seconds since 1/1/70:").
So, which one is right, the comment or the sample program???

matt
-- 
Matthew Reedy                 UUCP: uunet!iquery!matt
IQ Software Corporation       Internet: matt@iqsc.COM
400 N Loop 1604 E, Suite 100
San Antonio, TX  78232        (512) 490 6684  Fax: (512) 490-3590