HDTenEightyP/NetNews huggingface dataset:
From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.std.c
Subject: C arrays.
Date: 24 Nov 92 01:49:55 GMT
Organization: Comp Sci, RMIT, Melbourne, Australia

I have been having an argument with someone who thinks I am a dolt about C.
This may be so.  I would like to correct my understanding.

Is there anything which Pascal arrays _can_ do that C arrays can _not_
do, other than the following three compile-time issues:

    (a) Pascal arrays may be _declared_ as having an enumeration type
	for a particular index.  In both languages enumerations may be
	_used_, but only Pascal can require it.  Under the influence
	of Ada I count 'char' as an enumeration type.

    (b) Pascal arrays may have lower bounds other than 0.

    (c) Pascal arrays may be assigned and passed by value without
	first being wrapped in a "struct".  (That is, the _effect_ of
	assigning arrays and passing them by value may be concisely
	obtained in standard C, but not _directly_.)

In particular, my understanding is that when it comes to checking
array subscripts, Pascal and C are identical save in one respect.
They are identical in that both standards _permit_ but in no wise
_require_ subscript checking (compile-time or run-time).  The one
difference is that given
	SomeType a[N];			a: array [1..N] of SomeType;
both languages permit
	x = a[i];			x := a[i+1];
	a[i] := x;			a[i+1] := x;
for precisely the same values of i, but C additionally permits
the formation of the pointer
	&a[i]	for 0 <= i <= N
while Pascal implicitly permits this only for 0 <= i < N.

In this case we have something that C arrays _can_ do and Pascal
arrays can _not_.  There are other many other things that can be
done with C arrays but not Pascal arrays.

The person who thinks I am a dolt about C claims that C is a more "bare
bones" language than Pascal, and explicitly cites arrays as something that
Pascal supports and C doesn't.  Apart from the three points (a), (b), and
(c) above, I cannot at the moment recall any single construct which Pascal
arrays support and C arrays do not.  (Conformant array parameters do not
count:  they are optional in the ISO standard and absent from the ANSI one.)

I am posting in this group because the interesting question is what the
C _standard_ says about arrays, not what any particular implementation may
do.

As a further point which does not deserve a separate posting,
my understanding is that in the context

	#include <math.h>

	... float x, y;
	... x = sqrt(y);

a C processor may use a single-precision version of sqrt().  This is
certainly so for the arithmetic operators like +; is it also so for
the math functions?  I have a copy of the draft specification of the
math functions for Ada; that includes fairly tight bounds on precision.
I am informed that the C standard does _not_ contain tight bounds on the
precision of the math functions, so the answer to my question may be
"yes, because the standard doesn't specify sqrt() tightly enough to tell
the difference."

(For what it's worth, I put in another request for a copy of the standard
about two months ago.)
Newsgroups: comp.std.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: Header files and "hidden built-in type hacks".
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Tue, 17 Nov 1992 00:45:38 GMT

If anyone sees this article twice, please e-mail diamond@jit081.enet.dec.com.
I removed it from comp.std.unix this time in hopes of seeing it get posted.

In article <1e6nslINN4rd@ftp.UU.NET> rfg@netcom.com (Ronald F. Guilmette) writes:
>Certain of the functions which must be declared (preferably with prototypes)
>in the <stdio.h> file (e.g. vprintf) are defined (by the ANSI C standard) to
>take arguments of type `va_list'.

If a user's program declares printf instead of doing #include <stdio.h> then
the user's program must include a prototype with ellipsis ", ...".
If you're talking about the internals of the implementation's <stdio.h> then
the implementation is allowed to encode the declarations however it likes,
not necessarily encoded in the C language, not necessarily using prototypes
-- the implementation can choose any method that works for itself.

>But careful implementors know that if `va_list' is declared whever <stdio.h>
>is included, this will cause an small but unnecessary (and possibly illegal)
>pollution of the user's namespace.
>My first question is simply this.  Is the practice of avoiding definition
>of a va_list type in <stdio.h> strictly required by the ANSI C standard?

Yes.  s/possibly//  And carelessness yields non-conforming implementations.

>In what other cases are such "hidden built-in type hacks" required as a result
>of other requirements in the ANSI C standard (or in POSIX 1003.1-1990)?

It's probably easiest to encode hidden built-in type hacks for EVERYTHING and
avoid exactly this worry (assuming that you're an implementor).

[Examples deleted:  size_t in <time.h> and time_t in <sys/stat.h>]

ANSI C section 4.12.1, page 171 line 12, says that <time.h> declares size_t.
I don't have the POSIX standard.

>Volume-Number: Volume 29, Number 70

Is this an index to your encyclopedia of bugs in the ANSI C standard?
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"It's been a lovely recession."
Newsgroups: comp.std.c
From: rhl@grendel.Princeton.EDU (Robert Lupton the Good)
Subject: Casting const; Is this standard conforming?
Originator: news@nimaster
Organization: Princeton University
Date: Mon, 16 Nov 1992 20:08:43 GMT

I've never used const modifiers, so I assumed that this would be OK,

#include <stdio.h>

int
main()
{
   const int i = 0;
   
   (int)i = 1;				/* Fails */
   *(int *)&i = 1;			/* OK */
	    
   return(0);
}
	       
Thinking about ROMs my guess is that gcc and the IBM xlc compilers are
correct to reject the former assignment, and that their acceptance of
the latter is permitted, but could anyone comment? 

What do you think about the portability of the cast? (I want to set
the variable once in a private place just after mallocing it, in case
you wonder why I am trying to get around a const restriction, and
don't see why I can't just initialise it)

			Robert
			
-- 

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Robert Lupton                                           rhl@astro.princeton.edu
(609) 683 8252 (Home)					(609) 258 3811 (Work)
From: martin@datacomm.ucc.okstate.edu (Martin McCormick)
Newsgroups: comp.std.c
Subject: Re: POSIX means *Binary* Compatibility !  NOT !
Date: 21 Nov 92 13:56:54 GMT
Article-I.D.: osuunx.1992Nov21.135654.13538
Organization: Oklahoma State University, Stillwater, OK


Wow! I could get the source code for a full BSD version of Unix and compile
it and . . . . .  That's what I'll do with my old Apple II.  I didn't know
life could be so easy.

Martin McCormick WB5AGZ   Stillwater, OK
O.S.U. Computer Center Data Communications Group
Newsgroups: comp.std.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: fwrite+fread of pointer
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Tue, 17 Nov 1992 07:17:38 GMT

In article <15976@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>In article <1992Nov15.065204.22137@sq.sq.com>, msb@sq.sq.com (Mark Brader) writes:
>> First, I take it that everyone agrees that the bytes read back from
>> the file have to be the same ones that were written out.  The question
>> then is whether the bytes that represent the pointer value &dummy have
>> to always be the same ones, during the life of the variable "dummy".

>That is indeed the question.

Uh, that was my question, and I thought that was your question, but then
you proceed to suggest that your real question was a bit different....

>I have been arguing for a while in comp.lang.c that it would be
>a good thing if C compilers were to warn about fwrite(&x... or fread(&x...
>where x is of a type which can include pointers.  I have seen too many
>students get this wrong.  It is a particularly easy mistake to make:
>	struct Tag { ... char field[20]; ... } x;
>	fwrite(&x, sizeof x, 1, f);
>and then the instructor points out that `field' is supposed to hold
>file names and 20 is absurdly small, so the student changes it to
>	struct Tag { ... char *field; ... } x;
>and misses a couple of the fwrite()s.
[...some other argue that it might be useful...]
>[...]is it EVER possible for a _portable_ program to write out a pointer
>and usefully read it back?

The ability to write pointers might be useful.  As a pedantic example,
an interpreter might create a core dump of a subject program.  The ability
to write the bytes and read them back is certainly possible and portable.

However, you have certainly demonstrated that a warning would be useful,
at least for some users in some cases.  The standard certainly allows such
warnings, and quality of implementation might suggest an option.  It's only
a matter of opinion whether the default have them enabled or disabled.
It seems that this is the question you really wanted to ask, and the
answer seems to be clear enough.

>The question can now be paraphrased:  is a pointer like a tensor, or like
>the components of a tensor?  I would regard a compacting garbage collector
>as simply changing the co\"ordinate system.  I have used hardware and
>software systems where stacks could be moved (in order to "stretch" them)
>while the owning thread was running.

Well, obviously in virtual memory, and less obviously in some other
addressing techniques, it is possible to move objects and keep existing
pointers meaningful without changing them.  And the C standard doesn't
talk about tensors or components of tensors; an implementation could make
pointers be even more obscure as long as the results are correct.  Now,
how many results have to be guaranteed?  That's the same old hard question.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"It's been a lovely recession."
Newsgroups: comp.std.c
From: johnl@iecc.cambridge.ma.us (John R. Levine)
Subject: Re: strcmp() on a non-nil-terminated string
Organization: I.E.C.C.
Date: Tue, 17 Nov 1992 04:53:56 GMT

>> #include <string.h>
>> char first[]="first";
>> char second[]={'s','e','c','o','n','d'};
>> main()
>> { return!!strcmp(first,second); }
> 
>> Is this program allowed to behave undefined?
>Yes. ...
>> If so, can anyone imagine provide an example when this might happen?

Let's imagine a hypothetical CPU to which we'll give the made-up name of
Intel 80386DX-25.  This CPU has an instruction to scan bytes at high speed
looking for a given byte value, and to compare two byte arrays stopping when
a byte that doesn't match is found.  Both of these instructions take a
byte count to give the string length.  So the fastest version of strcmp()
is roughly this:

	scan arg1 for \0 to get its length, call it L
	compare arg1,arg2, length L

Even though this looks at each byte of arg1 twice, it's considerably faster
than a loop because it uses the fast string instructions.  If the arg1
argument isn't null-terminated, the initial scan could easily fly off the
end of the page causing various address faults.

Other machines with string scanning instructions, e.g. Vax and NS32032
would probably have strcmp() routines that'd fail the same way with
unterminated strings.

-- 
John R. Levine, IECC, POB 349, Cambridge MA 02238, +1 617 492 3869
johnl@iecc.cambridge.ma.us, {ima|spdcc|world}!iecc!johnl
"Time is Money!  Steal some today!"
Newsgroups: comp.std.c
From: eggert@twinsun.com (Paul Eggert)
Subject: Re: Return values from recursive function
Organization: Twin Sun, Inc
Date: Tue, 24 Nov 1992 03:08:27 GMT

dbbergac@sanluis (Dave Bergacker) writes:

>int streq(const char *s1, const char *s2)
>{
>  if ( !*s1 || ( *s1 != *s2 )) return *s1 - *s2;
>  else streq(++s1,++s2);
>}

>Does ANSI specify anything about this behavior?

Yes.  The C Standard says the behavior is undefined.

>This code worked on Borlands TC (version unknown) and gcc version 2.2.2.

``Undefined'' means the implementation can do anything it pleases -- it
can even do what the programmer meant!  An implementation need not
diagnose this error.  But you should tell your students to use their
compilers' debugging options; e.g. `gcc -Wall' diagnoses this error.
Newsgroups: comp.std.c
From: jes@grendel.demon.co.uk (Jim Segrave)
ReplyTo: jes@grendel.demon.co.uk
Subject: idle query on strtok()
Distribution: world
X-Mailer: cppnews $Revision: 1.19 $
Organization: None
Date: Tue, 17 Nov 1992 22:19:53 +0000


Is strtok()'s behaviour defined for tokens already taken from a string?

For example, suppose I have:
    char zoe[] = "aaa bbb";
    char *first, *second;
If I do:
    first = strtok (zoe, " "); 
    second = strtok (NULL, " ");
    printf ("%s\n%s\n", first, second);
I expect the output:
    aaa
    bbb

First idle query:

Can I *portably* change the contents of a token returned by strtok
without affecting the behaviour of subsequent calls?
If I do:
    first = strtok (zoe, " "); 
    printf ("%s\n", first);
    strcpy (first, "!!!");		/* corrupt the first bit */
    second = strtok (NULL, " ");
    printf ("%s\n", second);

Do I have a guarantee that I'll get the same output?
What if I change the 'corrupt ...' line to
    memset (first, 0, strlen (first) + 1);

Second idle query:

Does strtok() promise that the tokens delivered will be untouched
by subsequent calls to strtok()? Could a conforming implementation
keep the original pointer to the string to be tokenised and use the
string itself to retain state (say by filling from the start of the string
through to the last token delivered with some absurd character)?

I've never met an implementation which did care about previously
delivered tokens or which went back and wantonly trashed them, but I've
never seen any documentation which says that a perverse implementor
couldn't choose to do this.

--
Jim Segrave (Segrave Software Services)     jes@grendel.demon.co.uk
From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.std.c
Subject: Re: fwrite+fread of pointer
Date: 16 Nov 92 09:33:15 GMT
Organization: Comp Sci, RMIT, Melbourne, Australia

In article <1992Nov15.065204.22137@sq.sq.com>, msb@sq.sq.com (Mark Brader) writes:
> First, I take it that everyone agrees that the bytes read back from
> the file have to be the same ones that were written out.  The question
> then is whether the bytes that represent the pointer value &dummy have
> to always be the same ones, during the life of the variable "dummy".

That is indeed the question.  For the benefit of some comp.std.c readers
who have mistaken me for a novice who _wants_ to do this kind of thing,
I'm not.  I have been arguing for a while in comp.lang.c that it would be
a good thing if C compilers were to warn about fwrite(&x... or fread(&x...
where x is of a type which can include pointers.  I have seen too many
students get this wrong.  It is a particularly easy mistake to make:

	struct Tag { ... char field[20]; ... } x;
	fwrite(&x, sizeof x, 1, f);

and then the instructor points out that `field' is supposed to hold
file names and 20 is absurdly small, so the student changes it to

	struct Tag { ... char *field; ... } x;

and misses a couple of the fwrite()s.  I received mail from several people
defending the fact that C compilers don't point out the problem, all of
them taking the line that it _might_ be useful, though none of them cited
an actual working program they had written or even read.  The question then
arose:  is it EVER possible for a _portable_ program to write out a pointer
and usefully read it back?

It was always clear that you should get the same _bytes_ back, but it was
not clear to me that it has to be the same _pointer_.  Mark Brader has
understood the question perfectly.

> My opinion is that they do; this opinion is based, somewhat shakily,
> on the definition of an object as "a region of data space in the
> execution environment", where the key word is "a".

The question can now be paraphrased:  is a pointer like a tensor, or like
the components of a tensor?  I would regard a compacting garbage collector
as simply changing the co\"ordinate system.  I have used hardware and
software systems where stacks could be moved (in order to "stretch" them)
while the owning thread was running.
From: clive@x.co.uk (Clive Feather)
Newsgroups: comp.std.c
Subject: Re: fwrite+fread of pointer
Date: 18 Nov 92 13:18:09 GMT
Organization: IXI Limited, Cambridge, UK

In article <15976@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> The question can now be paraphrased:  is a pointer like a tensor, or like
> the components of a tensor?  I would regard a compacting garbage collector
> as simply changing the co\"ordinate system.  I have used hardware and
> software systems where stacks could be moved (in order to "stretch" them)
> while the owning thread was running.
 
An "object" is defined (ISO 3.14) as a "region of storage". I would read
this as meaning that, for the lifetime of that object, a given object
maps to a given region of storage. Therefore, since the address of an
object is a pointer to it, the address must also be a constant. I agree
that the ice is thin and an RFI would be a good idea. You might also ask
whether &external_object_or_function has to be the same in all the
translation units of a program.

This is all, of course, modulo the "as-if" rule. Mark Brader has shown a
way to have objects move in memory whilst keeping constant addresses;
this doesn't alter what I have said.

-- 
Clive D.W. Feather     | IXI Limited         | If you lie to the compiler,
clive@x.co.uk          | Vision Park         | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4RZ |   - Henry Spencer
Fax:   +44 223 236 550 | United Kingdom      |
Newsgroups: comp.std.c
From: diamond@jit345.bad.jit.dec.com (Norman Diamond)
Subject: Re: Casting const; Is this standard conforming?
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Tue, 17 Nov 1992 06:58:21 GMT

In article <1992Nov16.200843.5565@Princeton.EDU> rhl@grendel.Princeton.EDU (Robert Lupton the Good) writes:
>#include <stdio.h>
>   const int i = 0;
>   (int)i = 1;				/* Fails */
>   *(int *)&i = 1;			/* OK */
>Thinking about ROMs my guess is that gcc and the IBM xlc compilers are
>correct to reject the former assignment,

Thinking about the standard, where it says that the result of a const is
not an lvalue, you should know that every conforming implementation is
correct to reject the former assignment.

>and that their acceptance of the latter is permitted,

Yes.  The latter assignment is allowed to have any effect at all, without
even needing to be documented by an implementation.  Acceptance is legal.

>What do you think about the portability of the cast?

The cast is portable.  The attempted modification of a const object (i)
through use of a non-const lvalue (*(int *)&i) is allowed to succeed,
fail, dump core, or print some advice that you should buy a standard.

>(I want to set the variable once in a private place just after mallocing it,

malloc a non-const variable, set it once, and then copy the address to a
pointer-to-const-int.  Then pass around the const version.
--
Norman Diamond       diamond@jit081.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
"It's been a lovely recession."
Xref: sparky comp.std.c:3043 comp.unix.questions:13686
From: rob@hp11 (Rob Freyder)
Newsgroups: comp.std.c,comp.unix.questions
Subject: POSIX means *Binary* Compatibility !  NOT !
Date: 20 Nov 92 16:53:45 GMT
Followup-To: comp.std.c

8-)

Hi,

Just  had  a  conversation with a consultant regarding POSIX. According to
this  consultant  if  I  compile a POSIX program with a POSIX compiler the
resultant binary will run on any machine that supports the POSIX std. !

I  found  this  very  amusing. For example if I compile on my SUN Sparc II
the  binary  can  be  copied  unmodified  to  my  HP 730 Snake box and run
unmodified !   Amazing story 31b !!!

Has anyone done this ?

Rob.



--
Rob Freyder                             Atlas Wireline a division of
____    ____     ____                   Western Atlas International Inc.
\   \  /   /\   /   /\                  A Litton / Dresser Company
 \   \/   /  \ /   /  \                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  \  /   / \  /   /\   \                Internet  :  rob@marley.aws.waii.com
   \/___/   \/___/  \___\               Voice     :  (713) 972-6678
From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.std.c
Subject: Re: fwrite+fread of pointer
Date: 16 Nov 92 09:42:07 GMT
Organization: Comp Sci, RMIT, Melbourne, Australia

In article <1992Nov13.184421.11065@taumet.com>, steve@taumet.com (Steve Clamage) writes:
: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
: >I would like to know what the standard says about the following program:
: [ writes the contents of a pointer with fwrite, reads it back with fread ]
: [ that is, whether the value read == the value written ]
: 
: ANSI C Standard 4.9.2:
: 
: "Data read in from a binary stream shall compare equal to the data that
: were earlier written out to the stream, under the same implementation."
: 
: In the example, the file was opened in binary mode, so this applies.

That is exactly the kind of answer I hoped for when I posted to comp.std.c.
Thank you.  There remains, alas, one fine point of detail.  What does it
_mean_ to say "COMPARE EQUAL to the data ..."?

Consider this example:

	static struct foo {char a, b;} x, y = {2,3};
	fwrite(&x, sizeof x, 1, f);
	rewind(f);
	fread(&y, sizeof y, 1, f);

In this case, it is not possible to ask the question x == y because
== is not defined on structs.  So "compare equal" cannot refer to ==
but must refer to something like memcmp().  But I always did accept that

	char dummy;
	char *p = &dummy;
	char block[sizeof p];

	memcpy(block, &p, sizeof p);
	fwrite(&p, sizeof p, 1, f);
	rewind(f);
	fread(&p, sizeof p, 1, f);

must yield a state in which

	memcmp(block, &p, sizeof p) ==> 0

The question is whether the fact that the current value of p has the
same _bytes_ that it used to have means that it is necessarily the
same _pointer_.  The thing is, the wide licence allowed to casts has
taught me to be very cautious about assuming much when pointers and
bits are involved.  I know that casts are conversions, not merely type
relabellings, and that fwrite() and fread() do not involve casts.  I
mention casts only to explain why I am perhaps excessively wary.
From: dbbergac@sanluis (Dave Bergacker)
Newsgroups: comp.std.c
Subject: Return values from recursive function
Date: 23 Nov 1992 23:52:36 GMT
Organization: University of Colorado at Colorado Springs
NNTP-Posting-Host: sanluis.uccs.edu
X-Newsreader: TIN [version 1.1 PL6]


Hi, I teach a 'C' class, and in a recent assignment, a student turned in
code that looks like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
  char *s1 = "mom", *s2 = "dad";
  int streq(const char *s1, const char *s2);

  printf("Comparing strings %s and %s\n",s1,s2);
  printf("The result was %d\n",streq(s1,s2));
  printf("The C strcmp function returns %d\n",strcmp(s1,s2));
}

int streq(const char *s1, const char *s2)
{
  if ( !*s1 || ( *s1 != *s2 )) return *s1 - *s2;
  else streq(++s1,++s2);
}

Notice that there was no explicit return from the else branch, yet this
code worked on Borlands TC (version unknown) and gcc version 2.2.2.  Does
ANSI specify anything about this behavior? Regretably I do NOT have a
copy of the standard.
--
Happy Holidays,
	Dave Bergacker
The opinions expressed are not those of UCCS, nor should they be.
Newsgroups: comp.std.c