[comp.lang.c] time

daveh@marob.masa.com (Dave Hammond) (10/07/89)

In article <252BFD80.194C@marob.masa.com> I wrote about problems using
time().  The mysterious clock problems turned out to be simply a matter
of a particular routine "assuming" that a standard header had properly
declared time(), when in fact that was not so.  The clock "flip-flop"
effect was the result of taking the time() value as a 32-bit quantity in
some places and a 16-bit quantity in others.

I apologize to the net for wasting bandwidth with this problem, as a
simple "linting" would have pointed me in the right direction.

My thanks to Tim Olson (tim@amd.com) for replying so quickly and
pointing out what should have been obvious.

--
Dave Hammond
daveh@marob.masa.com

james@castle.ed.ac.uk (J Gillespie) (02/04/91)

Is there a simple way of getting hold of the system time from within a
C program?  I've read all the material I can find on time.h, but can't
make head or tail of it, and have had to resort to passing in the time
as a command line argument.  This may be a really idiotic question,
-- 
  James Gillespie,     /~~~~~~~~\
 Edinurgh University. /   @  @   \    "I'm not musical either - 
   james@ed.ac.uk    /     <      \               I play the bagpipes"
____________________/  \________/  \__________________________________________

james@castle.ed.ac.uk (J Gillespie) (02/06/91)

Thankyou to everyone who e-mailed me an explanation; I've got stacks
of them now, and have got over my difficulty with all of the time
functions I've tried.
-- 
  James Gillespie,     /~~~~~~~~\    "Looks fast!"
 Edinurgh University. /   @  @   \   "Yeah.  That's the stripes, man."
   james@ed.ac.uk    /     <      \				   -- Fandango
____________________/  \________/  \__________________________________________

rana@hpqtdla.sqf.hp.com (Rana Raychoudhury) (02/07/91)

> Is there a simple way of getting hold of the system time from within a
> C program?  I've read all the material I can find on time.h, but can't
> make head or tail of it, and have had to resort to passing in the time
> as a command line argument.  This may be a really idiotic question,
> -- 
>   James Gillespie,     /~~~~~~~~\
>  Edinurgh University. /   @  @   \    "I'm not musical either - 
>    james@ed.ac.uk    /     <      \               I play the bagpipes"
> ____________________/  \________/  \__________________________________________

(I assume you mean "time of day" and are using an ANSI compiler :-

 [From the 'C Programming Language, 2nd Edition pp256-7]

 .... 

 char *asctime(const struct tm *tp)
  
 converts the time in the structure *tp into a string of the form

 Sun Jan  3 15:14:13 1988\n

 char *ctime(const time_t *tp)

 converts the calendar time *tp to local time; equivalent to :-

 asctime(localtime(tp));

 blah blah blah.

 Here's a little example :-

---------------- snip snip --------------
#include <time.h>

time_t now;

main()
{
  (void) time( &now );
  printf("The time is : %s\n", asctime(localtime(&now)));
}
---------------- snip snip --------------

 which produces something like :-

The time is : Wed Feb  6 17:27:15 1991


-rana-

murison@cfa.HARVARD.EDU (Marc A. Murison, RG) (02/07/91)

From article <8258@castle.ed.ac.uk>, by james@castle.ed.ac.uk (J Gillespie):
> 
> Is there a simple way of getting hold of the system time from within a
> C program?

Here's how I do it:

#include <time.h>
#include <stdio.h>
void main( void )
{
    time_t  cur_time;

    /* get the current date and time */
    time(&cur_time);

    /* ctime() converts a value of type time_t to a string */
    printf( "\ncurrent time = %s", ctime(&cur_time) );
}


Marc Murison
Smithsonian Astrophysical Observatory
murison@cfacx2.harvard.edu   (the address in the header will bomb)

martin@mwtech.UUCP (Martin Weitzel) (05/21/91)

In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
[...]
>	long seed = time(0L);
	                 ^^--------- wrong
	           time((long *)0);
	                ^^^^^^^^^--- right

Note that the argument to the time system call is a `long *', aka
pointer to long. Repeat after me: POINTER to long.

But I've seen this too often, even in examples printed in some manuals.
Though I had not much confidence into those particular manuals where
I found it (for reasons that probably aren't of any interrest to the
readers of this group), I'm curious if anybody has ideas from where this
misconception originated.

Or, if you have two minutes and you have some source code from which you
suppose that it contains a time system call, just grep through it and
look if it's done right. I'm always wondering why people can't grasp
the difference between a plain integer, a long and pointers to any of it.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

lothar@tmcsys.UUCP (L. Hirschbiegel) (05/22/91)

In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>[...]
>>	long seed = time(0L);
>	                 ^^--------- wrong
>	           time((long *)0);
>	                ^^^^^^^^^--- right
>

You're a cousin of "lint", aren't you :-) ?

>Note that the argument to the time system call is a `long *', aka
>pointer to long. 

Ever tried to RTFM for yourself? 

	  NAME
	       time - get time

	  DESCRIPTION
	       The time	system call returns the	value of time in seconds
	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.

	       If tloc is non-zero, the	return value is	also stored in the
                   ^^^^^^^^^^^
	       location	to which tloc points.

If you still don't understand: I'll help you! 
For this little test program:

main()
{
time(0L);
time((long *)0);
}

the assembler output from my C compiler is:

	.file	"main.c"
gcc_compiled.:
.text
	.align 4
.globl main
main:
	pushl %ebp
	movl %esp,%ebp
	pushl $0
	call time
	pushl $0
	call time
.L1:
	leave
	ret

>Repeat after me: POINTER to long.

Repeat after me: IT DOESN'T MATTER :-)

>I'm always wondering why people can't grasp
>the difference between a plain integer, a long and pointers to any of it.

So do I...

>-- 
>Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

Lothar Hirschbiegel
-- 
-----------------------------------------------
L. Hirschbiegel, AEG - A84, Frankfurt (Germany) 
email: unido!aega84!lh     tel: -49-69-66414316  
-----------------------------------------------

gwyn@smoke.brl.mil (Doug Gwyn) (05/22/91)

In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>>	long seed = time(0L);
>I'm curious if anybody has ideas from where this misconception originated.

The roots of many such errors are probably unknown even to the original
culprits.

In this particular case, my best guess is that the common "time(0)" usage
was "repaired" during port to a system where it mattered, and the person
doing the repair was thinking merely of the required representation for
the argument to work right, not more abstractly in terms of its type.
You can see this also in the common
	#define	NULL	0L

gwyn@smoke.brl.mil (Doug Gwyn) (05/22/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
>Ever tried to RTFM for yourself? 
>	       If tloc is non-zero, the	return value is	also stored in the
>                   ^^^^^^^^^^^

That's what you get for looking in a buggy FM!

>If you still don't understand: I'll help you! 

Martin understands just fine.

>Repeat after me: IT DOESN'T MATTER :-)

Oh, yes it does -- if your application is any good, some day it might be
ported to a platform other than the specific environment you used in your
testing.

ckp@grebyn.com (Checkpoint Technologies) (05/22/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
>In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>>[...]
>>>	long seed = time(0L);
>>	                 ^^--------- wrong
>>	           time((long *)0);
>>	                ^^^^^^^^^--- right
>>
>>Note that the argument to the time system call is a `long *', aka
>>pointer to long. 
>
>Ever tried to RTFM for yourself? 
>
>	  NAME
>	       time - get time
>
>	  DESCRIPTION
>	       The time	system call returns the	value of time in seconds
>	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.
>
>	       If tloc is non-zero, the	return value is	also stored in the
>                   ^^^^^^^^^^^
>	       location	to which tloc points.

You omitted the SYNOPSIS for time: "time_t time(tloc) time_t *tloc;",
which clearly shows that the argument to time() is a pointer to a
time_t (which BTW is the *real* correct answer).  This man page uses an
archaic style when using the term "non-zero".  Read the FAQ for the whole
poop on NULL and 0; there is a place in C where 0 is treated as
NULL, but arguments to functions sans prototype isn't one of them.

>For this little test program:
>
>main()
>{
>time(0L);
>time((long *)0);
>}
>
>the assembler output from my C compiler is:
> [ omitted; irrelevant ]

BIG mistake.  The assembly language output from the C compiler shows all
the implementation details, including the ones which are not guanteed to
be portable.  You will not learn portable C programming this way, quite
the opposite.  There's no favor from anyone in comp.lang.c for
arguing how widely applicable implementation details are; all the
world's NOT a VAX or i386...

>>Repeat after me: POINTER to long.
>Repeat after me: IT DOESN'T MATTER :-)

Too many programmers repeat after you as it is.  It does matter.
-- 
Richard Krehbiel, private citizen      ckp@grebyn.com
(Who needs a fancy .signature?)

jeff@uf.msc.umn.edu (Jeff Turner) (05/22/91)

In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>[...]
>>	long seed = time(0L);
>	                 ^^--------- wrong
>	           time((long *)0);
>	                ^^^^^^^^^--- right
>
>Note that the argument to the time system call is a `long *', aka
>pointer to long. Repeat after me: POINTER to long.

You are right -- to ensure portability, you should always pass what is expected
(i.e. a pointer and not a long).  This way, if someday a machine is created 
on which a pointer to a long is a different size then a long, the program will
still work.  However, I don't know of any machines on which the two differ.

Perhaps you are confusing time(0) with time(0L).  Calling time(0) on a 16-bit
machine (e.g. PCs not running 386 UNIX) will push only a 16 bit value onto the
stack instead of the 32 bit address that time() is expecting (and is going to
use).  Since half of the 32-bit address will have a random (and probably
non-zero) value, time() will use it as an address to store the current time
into, and bash your memory or cause range-error core-dump.

I encountered this problem frequently back when I was running uPort's SysV/AT.
I found that passing NULL to time() (or to any other similar function) worked
in all cases as the value of NULL changes with the memory model (i.e. small
memory model defined it simply as 0, whereas large memory model defined it
as 0L).  Of course by definition, passing (long*)0 is the only truely correct
way to pass a long pointer that points to address 0, but that is toooooooo
much to type :-)

-Jeff
---
Jeff Turner                           EMAIL: jeff@msc.edu
Minnesota Supercomputer Center, Inc.  VOICE: (612) 626-0544
Minneapolis, Minnesota  55415           FAX: (612) 624-6550

tim@dell.co.uk (Tim Wright) (05/22/91)

In <381@tmcsys.UUCP> lothar@tmcsys.UUCP (L. Hirschbiegel) writes:

>In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>>[...]
>>>	long seed = time(0L);
>>	                 ^^--------- wrong
>>	           time((long *)0);
>>	                ^^^^^^^^^--- right
>>

>You're a cousin of "lint", aren't you :-) ?

>>Note that the argument to the time system call is a `long *', aka
>>pointer to long. 

>Ever tried to RTFM for yourself? 

>	  NAME
>	       time - get time

>	  DESCRIPTION
>	       The time	system call returns the	value of time in seconds
>	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.

>	       If tloc is non-zero, the	return value is	also stored in the
>                   ^^^^^^^^^^^
>	       location	to which tloc points.

>If you still don't understand: I'll help you! 
>For this little test program:

Yes but it's a pointer i.e. they are talking about a non-zero or non-null
pointer. If the compiler allows prototypes, it can cast a 0 correctly.
Without prototypes it cannot.

>main()
>{
>time(0L);
>time((long *)0);
>}

>the assembler output from my C compiler is:
...
irrelevant :-)

>>Repeat after me: POINTER to long.

>Repeat after me: IT DOESN'T MATTER :-)

*WRONG* *WRONG* *WRONG*. Just because it doesn't happen to matter on
*YOUR* machine with *YOUR* C compiler does not mean it does not matter.
On a non-ansi compliant compiler on a '286 system it is possible to
choose a memory model where sizeof(long) != sizeof(long *).
In this case the code generated will be somewhat different :-)

Tim
-- 
Tim Wright, Dell Computer Corp., Bracknell    |  Domain: tim@dell.co.uk
Berkshire, UK, RG12 1RW. Tel: +44-344-860456  |  Uucp: ...!ukc!delluk!tim
Smoke me a Kipper, I'll be back for breakfast - Red Dwarf

david@sco.COM (David Fiander) (05/22/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
>
>You're a cousin of "lint", aren't you :-) ?
>

No, he's somebody that knows the difference between a null pointer and
the integer zero.

>Ever tried to RTFM for yourself? 
>
>	  NAME
>	       time - get time
>
>	  DESCRIPTION
>	       The time	system call returns the	value of time in seconds
>	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.

You missed a line which appears in _my_ FM:

	long *tloc;


>If you still don't understand: I'll help you! 
>For this little test program:
>
>main()
>{
>time(0L);
>time((long *)0);
>}
>
>the assembler output from my C compiler is:
>
> [assembler code deleted,  I try to avoid it]
>

So you're using GCC on an intel platform (i386 obviously, it wouldn't fit
on anything else).

Lucky you, you've never had to program an Cyber 180.  If you tried that
trick on any CDC machine , you would get a "Ring-0" hardware exception
and, if you hadn't installed a handler, your program could get blown off
(I think.  I never used NOS/VE, and what I used just caused a disgusting
penalty hit, since we trapped to the OS, it said "shithead programmer,"
and returned).

There exist architectures on which the NULL pointer is different from
"all bits 0".  In fact, if you can get the compiler people to agree to
it, the best value for the NULL pointer is something that is an invalid
virtual memory address, because then, when somebody tries to dereference
it, you get a core dump (note that 0 might be a valid address which would
never be referred to by the user, for example: the address of the C
startup code).  The large part of a project I was involved was spent
inserting necessary casts into function calls, in order to _fix_ code
written by people that believed 

>
>Repeat after me: IT DOESN'T MATTER :-)

--
David J. Fiander
SCO MMDF Development Team
SCO Canada, Inc.

clewis@ferret.ocunix.on.ca (Chris Lewis) (05/22/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
>In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>>[...]
>>>	long seed = time(0L);
>>	                 ^^--------- wrong
>>	           time((long *)0);
>>	                ^^^^^^^^^--- right

>Ever tried to RTFM for yourself? 

>	  DESCRIPTION
>	       The time	system call returns the	value of time in seconds
>	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.

>	       If tloc is non-zero, the	return value is	also stored in the
>                   ^^^^^^^^^^^
>	       location	to which tloc points.

You omitted the part where it defined time as:

	long time (long *tloc)

(Or, for that matter, "time_t time (time_t *tloc);")

Within context, the "non-zero" really means "non-null pointer to long(time_t)"

[I've even seen manual pages where they are out-and-out wrong.  I've
seen time(0) in some manual pages, and that won't work either]

>If you still don't understand: I'll help you! 
>For this little test program:

Lothar goes on to "prove" his point by test compiling a bit of C
and showing that "time(0L)" and "time((long *) 0)" compiles the same
way.  (on what looks like a 386 according to the assembler)

You're lucky.  Not all machines have pointers that are the same length
as longs.  Try this code on a PDP-11 or on many small mode 8086 compilers:

int func(a, b, c)
long *b; int a,c; {
	printf("%d:%d\n", a, c);
}

func(4, 0L, 4);

It won't print "4:4".  Some compilers will print "4:0", and some'll print "0:4",
and some will print garbage.

func(4, (long*)0, 4) will print 4:4.

Lint and Martin are correct.  Pointers aren't longs.  They ain't ints
either.

Didn't your math teacher tell you that you can't prove a theory on a single
example?  On the other hand, any theory can be disproved by a single
counter-example.
-- 
Chris Lewis, Phone: (613) 832-0541, Domain: clewis@ferret.ocunix.on.ca
UUCP: ...!cunews!latour!ecicrl!clewis; Ferret Mailing List:
ferret-request@eci386; Psroff (not Adobe Transcript) enquiries:
psroff-request@eci386 or Canada 416-832-0541.  Psroff 3.0 in c.s.u soon!

ed@mtxinu.COM (Ed Gould) (05/22/91)

>You are right -- to ensure portability, you should always pass what is expected
>(i.e. a pointer and not a long).  This way, if someday a machine is created 
>on which a pointer to a long is a different size then a long, the program will
>still work.  However, I don't know of any machines on which the two differ.

The machine on which this stuff was first developed - the PDP-11 - is
one.  It has 16-bit pointers.  So does any machine with a 64K address
space.  In fact, the early (Sixth Edition and before) form of the time()
call was

	time(t)
	int t[2];

In those days, "long" ints were represented explicitly as arrays
of two ints.  The time() function took (a pointer to) one of those.
It had no meaningful return value.

In Seventh Edition UNIX, by which time the C language had been
extended to include longs and typedefs, time() became

	time_t time(t)
	time_t *t;

Not too long ago, I saw a piece of code (in a large, now commercial,
software system that will remain nameless) that looked like this:

		time_t now;
	#if some_machine_type || some_other_machine_type
		now = time(0);
	#else
		now = time();
	#endif

Evidently, time() failed on those machines when passed no arguments,
so somebody "fixed" the bug.  I wish people would take the 15 or 20
seconds it takes to get something like this right.
-- 
Ed Gould			No longer formally affiliated with,
ed@mtxinu.COM			and certainly not speaking for, mt Xinu.

"I'll fight them as a woman, not a lady.  I'll fight them as an engineer."

torek@elf.ee.lbl.gov (Chris Torek) (05/23/91)

In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>... I'm curious if anybody has ideas from where this misconception
>[about the type of the argument to time()] originated.

Perhaps it dates back to Version 6 Unix, when C did not have a `long'
type.  The time() system call took a pointer to the first of two
`ints'.  In V7 this became a pointer to a long, but of course in V6
pointers and integers were freely interchangeable, and people wrote
such gems as

	struct xxreg {
		int	csr;	/* control/status */
		int	bar;	/* unibus address */
	};

	...
	0177440->bar = bp->b_addr;
	0177440->csr = XXREAD | XXGO;

One can speculate that `long' went in before `pointers are not ints',
and people changed their

	time(vec);

calls to

	t = time(0);

calls, but for backwards compatibility the time() function still
accepted pointers.  It still does; it should be `time_t time(void)',
but compatibility with 20-year-old software is oh so terribly
important :-) .

Perhaps if dmr is indulging his news habit and sees this, he might
comment....
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

jim@sco.COM (Jim Sullivan) (05/23/91)

lothar@tmcsys.UUCP (L. Hirschbiegel) writes:

>In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>>[...]
>>>	long seed = time(0L);
>>	                 ^^--------- wrong
>>	           time((long *)0);
>>	                ^^^^^^^^^--- right
>
>If you still don't understand: I'll help you! 
>For this little test program:
>
>main()
>{
>time(0L);
>time((long *)0);
>}
>
>the assembler output from my C compiler is:

	< assembly code illustrating that 0L and (long *)0 both map to 0 >

This if from YOUR C compiler.  And on many systems, similar code would be
produced.  But on many systems 0L and (long *)0 are not equal, so writers
of portable code should do the right thing and not assume that the entire
work is the same as their machine.

>
>Repeat after me: IT DOESN'T MATTER :-)

But it does. 

>>I'm always wondering why people can't grasp
>>the difference between a plain integer, a long and pointers to any of it.

Here! Here!


>>Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83
>Lothar Hirschbiegel

-- 
Jim Sullivan				"Revenue Canada:
SCO Canada, Inc.			 	You Make It
Toronto, Ontario, Canada		 	We Take It"
jim@scocan.com, ...!uunet!scocan!jim	- Backbench comic in the Globe

sef@kithrup.COM (Sean Eric Fagan) (05/23/91)

In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
>>	long seed = time(0L);
>	                 ^^--------- wrong
>	           time((long *)0);
>	                ^^^^^^^^^--- right
>Note that the argument to the time system call is a `long *', aka
>pointer to long. Repeat after me: POINTER to long.

On the other hand, if you have an ansi-conformant compiler, and a prototype
is in scope, then either solution will work properly.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

cpcahil@virtech.uucp (Conor P. Cahill) (05/23/91)

lothar@tmcsys.UUCP (L. Hirschbiegel) writes:

>Ever tried to RTFM for yourself? 
>If you still don't understand: I'll help you! 
>For this little test program:
>main()
>{
>time(0L);
>time((long *)0);
>}
>the assembler output from my C compiler is [the same for both.]
>Repeat after me: IT DOESN'T MATTER :-)

Boy, you just showed the world that you are a junior programmer who 
hasn't yet realized that just because something works on your system
doesn't mean it is right.  

The code you show won't work reliably on systems where the size of
a pointer is different from the size of an integer (for ex: large 
model programs on an 8086 or 80286). 

Before you jump on someone elses case, be sure you know what
you are talking about.
-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

toy@pegasus.crd.ge.com (Raymond L. Toy) (05/23/91)

In article <4138@uc.msc.umn.edu> you write:
|> In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
|> >In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
|>[...]
|> 
|> You are right -- to ensure portability, you should always pass what
is expected
|> (i.e. a pointer and not a long).  This way, if someday a machine is created 
|> on which a pointer to a long is a different size then a long, the
program will
|> still work.  However, I don't know of any machines on which the two differ.

Such machines do exist and are very common.  In particular, a PC has
this property when using the small memory model: a pointer is 16 bits
long, but a long is 32 bits.

Also, at school, we had a Harris H800 mini, a 24-bit machine.  A
pointer was 24 bits long (really only 22!!!), and a long was really 47
bits long!!!!  This was a rather bizarre machine, to say the least.
It's dead and gone now, fortunately.

Ray
ray ----> toy@soho.crd.ge.com

|> 
|> -Jeff
|> ---
|> Jeff Turner                           EMAIL: jeff@msc.edu
|> Minnesota Supercomputer Center, Inc.  VOICE: (612) 626-0544
|> Minneapolis, Minnesota  55415           FAX: (612) 624-6550

scotte@applix.com (Scott Evernden) (05/23/91)

Someone, please, anyone- 
Name for me any modern computer in any kind of common use which will
barf at:

	time(0L);

-scott

barmar@think.com (Barry Margolin) (05/23/91)

In article <1200@applix.com> scotte@applix.UUCP (Scott Evernden) writes:
>Name for me any modern computer in any kind of common use which will
>barf at:
>	time(0L);

I frequently respond to this frequent question with one or two machines I'm
familiar with, but I'm not going to do that this time.  Suffice it to say
that there *are* systems where the null pointer is not implemented as the
same bit pattern as 0L.

No, these systems are not "in common use".  90% of all C programs are
probably running on 80*86, 680x0, VAX, and SPARC processors, but does that
mean that all other systems should be ignored?

Prototypes are the most appropriate solution to this problem.  With a
prototype in scope, the above call works right on any ANSI-conforming
implementation.  But if you need to be portable to pre-ANSI
implementations, then is "(char *)0" so hard to write?  Not only does it
inform the compiler of the correct code to generate (in implementations
that care), but it also makes the intent clearer to *human* readers of the
code.  What's the point of looking for a way around something that's so
clearly right?
-- 
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

boyd@prl.dec.com (Boyd Roberts) (05/23/91)

In article <13455@dog.ee.lbl.gov>, torek@elf.ee.lbl.gov (Chris Torek) writes:
> 
> Perhaps it dates back to Version 6 Unix, ...

I think Chris is right.  If you look at any routine that requires a long
(in the `standard' C library) it'll be passed by a pointer.

One Computing Centre once changed ctime(3) to take a long instead of a long *.
Boy, were they sorry.  Broken code from here to backups...


Boyd Roberts			boyd@prl.dec.com

``When the going gets wierd, the weird turn pro...''

conor@lion.inmos.co.uk (Conor O'Neill) (05/23/91)

In article <4138@uc.msc.umn.edu> jeff@uf.UUCP (Jeff Turner) writes:
>You are right -- to ensure portability, you should always pass what is expected
>(i.e. a pointer and not a long).  This way, if someday a machine is created 
>on which a pointer to a long is a different size then a long, the program will
>still work.  However, I don't know of any machines on which the two differ.

Think of a 16-bit machine, where pointers are 16-bits, but longs are 32-bits.
Not a particularly obscure possibility.

(Oh - by the way - we sell one - the IMS T222 transputer).

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

imc@prg.ox.ac.uk (Ian Collier) (05/23/91)

In article <381@tmcsys.UUCP>, lh@aega84.UUCP (L. Hirschbiegel) wrote:
[about the argument of time()]
>	  NAME
>	       time - get time
>
>	  DESCRIPTION
>	       The time	system call returns the	value of time in seconds
>	       since 00:00:00 Greenwich	Mean Time (GMT), January 1, 1970.
>
>	       If tloc is non-zero, the	return value is	also stored in the
>                   ^^^^^^^^^^^
>	       location	to which tloc points.

Obviously the writers of your manual don't know the difference between a
long and a pointer, then. Ours seems to have it about right...

SYNOPSIS
...
     time_t time(tloc)
     time_t *tloc;

DESCRIPTION
     time() returns the time since 00:00:00 GMT,  Jan.  1,  1970,
     measured in seconds.

     If tloc is non-NULL, the return value is also stored in  the
                    ^^^^
     location to which tloc points.

>For this little test program:
...
>the assembler output from my C compiler is:
...

All that means is that your computer represents a NULL pointer by zero
(also evident from your manual page). So for time(0L) it pushes a long
zero, and for time((long *)0) it pushes a null pointer, which is just
a long zero. That will happen on most computers, but not all. (As
someone has pointed out, however, if a prototype for time() is in scope
then a zero will be converted into a null pointer, probably without a
warning message).

Ian Collier
Ian.Collier@prg.ox.ac.uk | imc@ecs.ox.ac.uk

pt@geovision.gvc.com (Paul Tomblin) (05/23/91)

scotte@applix.com (Scott Evernden) writes:

>Someone, please, anyone- 
>Name for me any modern computer in any kind of common use which will
>barf at:

>	time(0L);

Well, when I worked on a MVS/XA system, it probably would have barfed on that
line, but only because we didn't have a C compiler on it.....
:-)


//GO.SYSIN DD *, DO-DAH, DO-DAH
-- 
Paul Tomblin, Department of Redundancy Department.       ! My employer does 
Two roads diverged in a wood, and I/ I took the one less ! not stand by my
travelled by/ And that is why I'm lost, dammit...        ! opinions.... 
pt@geovision.gvc.com or {cognos,uunet}!geovision!pt      ! Me neither.

6sigma2@polari.UUCP (Brian Matthews) (05/23/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
|In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
|>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
|>[...]
|>>	long seed = time(0L);
|>	                 ^^--------- wrong
|>	           time((long *)0);
|>	                ^^^^^^^^^--- right
|Ever tried to RTFM for yourself? 
|
|	  NAME
|	       time - get time
|	       If tloc is non-zero, the	return value is	also stored in the
|                   ^^^^^^^^^^^
|	       location	to which tloc points.

You'll get yourself in trouble by taking parts of TFM out of context.
The part you left out reads something like:

	long time ((long *) 0)
	long time (tloc)
	long *tloc;

Tloc still has to be of the correct type, whether zero or non-zero.  This
can happen by having a prototype in scope or with an appropriate cast.

|If you still don't understand: I'll help you! 
|For this little test program:
|[program calling time with (incorrect) 0L and (correct) (long *)0]

This just proves that on your particular OS at some particular release
level and version with some particular version of gcc, it happens to
work.  In general, portable code must assume time(0L) won't work.

|Repeat after me: IT DOESN'T MATTER :-)

Please remind me never to use any code you've written.  It will
undoubtedly fail in many strange and mysterious (to you at least) ways.

jim@segue.segue.com (Jim Balter) (05/24/91)

In article <4138@uc.msc.umn.edu> jeff@uf.UUCP (Jeff Turner) writes:
>Of course by definition, passing (long*)0 is the only truely correct
>way to pass a long pointer that points to address 0, but that is toooooooo
>much to type :-)

By the ANSI standard, if there is a prototype in scope, a zero value of any
type is "correct".  Without a prototype, only (time_t *)0 is correct.

gwyn@smoke.brl.mil (Doug Gwyn) (05/24/91)

In article <1200@applix.com> scotte@applix.UUCP (Scott Evernden) writes:
>Name for me any modern computer in any kind of common use which will
>barf at:
>	time(0L);

Look, you're wasting our time.  Examples have been given many times in
this newsgroup previously, but anyway since it is NOT guaranteed to work
why don't just just accept that and do it right?

lothar@tmcsys.UUCP (L. Hirschbiegel) (05/24/91)

In article <1991May22.190908.5311@virtech.uucp> cpcahil@virtech.uucp (Conor P. Cahill) writes:
>
>The code you show won't work reliably on systems where the size of
>a pointer is different from the size of an integer (for ex: large 
>model programs on an 8086 or 80286). 

This was posted to newsgroup "comp.UNIX.SYSV386", right??
This was NOT posted to newsgroup "comp.unix.any_intel_product", right??
The original poster had problems with SCO-UNIX password generator, not
with a password generator running under MS-C6.0 in tiny-mode, right??

Martin was referring to a "time" syscall argument mismatch under SCO-UNIX.
I pointed out, that it really makes no difference for the argument value itself.
I did NOT say this is a general rule-of-thumb for all kinds of cpus
and all kinds of compilers?!?!

>Before you jump on someone elses case, be sure you know what
>you are talking about.

Before you answer in a newsgroup make sure you realise what that newsgroup
is about.

>Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.

-- 
-----------------------------------------------
L. Hirschbiegel, AEG - A84, Frankfurt (Germany) 
email: unido!aega84!lh     tel: -49-69-66414316  
-----------------------------------------------

jim@segue.segue.com (Jim Balter) (05/24/91)

In article <1991May22.130713.25852@sco.COM> david@sco.COM (David Fiander) writes:
>There exist architectures on which the NULL pointer is different from
>"all bits 0".

This isn't relevant if using ANSI prototypes, since any form of zero is
implicitly converted to the appropriate null pointer, no matter how it is
represented.  If you aren't using ANSI prototypes, then you should manually
cast everything into the proper type, and run lint religiously.  Hopefully,
some day, we will only concerned with the first case.

>In fact, if you can get the compiler people to agree to
>it, the best value for the NULL pointer is something that is an invalid
>virtual memory address, because then, when somebody tries to dereference
>it, you get a core dump (note that 0 might be a valid address which would
>never be referred to by the user, for example: the address of the C
>startup code).

This doesn't require a non-zero representation of NULL, since page 0 of
the virtual address space can usually be made inaccessible.  Most UNIX systems
don't do it because there are too many bad UNIX programs written by too many
bad UNIX programmers, and any desire to do the "right" thing is overridden
by the market demand to allow programs that dereference NULL to continue to
"work".

cpcahil@virtech.uucp (Conor P. Cahill) (05/24/91)

lothar@tmcsys.UUCP (L. Hirschbiegel) writes:

>This was posted to newsgroup "comp.UNIX.SYSV386", right??

NO.  It was cross-posted to comp.unix.sysv386 AND comp.lang.c

>Martin was referring to a "time" syscall argument mismatch under SCO-UNIX.

Martin was saying that it was incorrect useage to call time(0L) period.

>I pointed out, that it really makes no difference for the argument value itself.
>I did NOT say this is a general rule-of-thumb for all kinds of cpus
>and all kinds of compilers?!?!

You did not say "it makes on difference under SCO UNIX".   You said it makes
no difference.  Either way (on SCO UNIX or not) it is incorrect to code 
time(0L) as opposed to time((long*)0).

>Before you answer in a newsgroup make sure you realise what that newsgroup
>is about.

Learn how to read headers.

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

jja@wsl.ie (John Allen on wsl) (05/24/91)

In article <1200@applix.com> scotte@applix.UUCP (Scott Evernden) writes:
>Someone, please, anyone- 
>Name for me any modern computer in any kind of common use which will
>barf at:
>
>	time(0L);
>
>-scott

I suppose this is a good a reason as you can come up with to do it 
inorrectly.

You belong to the old school of 'we used to do it wrong, we still do it wrong'

lbr@holos0.uucp (Len Reed) (05/24/91)

In article <1991May22.130713.25852@sco.COM> david@sco.COM (David Fiander) writes:
>There exist architectures on which the NULL pointer is different from
>"all bits 0".  In fact, if you can get the compiler people to agree to
>it, the best value for the NULL pointer is something that is an invalid
>virtual memory address, because then, when somebody tries to dereference
>it, you get a core dump (note that 0 might be a valid address which would
>never be referred to by the user, for example: the address of the C
>startup code).

Under what architecture is a NULL pointer not "all bits 0"?  The problems,
as many have said, result when a pointer has fewer or more bits than
an integer (or a long).  NULL pointers *are* all zeros, though, since
casting zero to a pointer must yield a null pointer.  (Maybe there's
a loophole here in ANSI that says that (void *)0 is a null pointer but
the compiler could implement that casted zero as somthing other than
a pattern of zeros.  Not likely in the real world.)

You're certainly right that a NULL that produced a virtual memory fault
upon any use would be better than a virtual zero address.  But it's not
the "compiler people" who would have to agree to this.  Far too much
existing code would be broken by a move to this, I'm afraid.
-- 
Len Reed
Holos Software, Inc.
Voice: (404) 496-1358
UUCP: ...!gatech!holos0!lbr

bright@nazgul.UUCP (Walter Bright) (05/25/91)

In article <4138@uc.msc.umn.edu> jeff@uf.UUCP (Jeff Turner) writes:
/Perhaps you are confusing time(0) with time(0L).  Calling time(0) on a 16-bit
/machine (e.g. PCs not running 386 UNIX) will push only a 16 bit value onto the
/stack instead of the 32 bit address that time() is expecting (and is going to
/use).  Since half of the 32-bit address will have a random (and probably
/non-zero) value, time() will use it as an address to store the current time
/into, and bash your memory or cause range-error core-dump.

Actually, in all the 16 bit compilers I'm currently familiar with,
time() is prototyped such that the argument is correctly cast, and the
problem doesn't arise. For instance, time(long *) being the prototype,
time(0) becomes time((long*)0) which will always work correctly.

The time you unavoidably get into trouble is if it is a varargs function
like printf().

lothar@tmcsys.UUCP (L. Hirschbiegel) (05/25/91)

>This just proves that on your particular OS at some particular release
>level and version with some particular version of gcc, it happens to
>work.  In general, portable code must assume time(0L) won't work.

To come to an end with this really annoying 'discussion' please accept
the following statement:
the whole thread of time(0L) vs. time((long *)0) was about
the **Intel i386 processor** running under **ISC/SCO-UNIX** (Martin 
Weitzel's posting as a reply and my own followup).
I didn't intend to crosspost this to com.lang.c but it happened somehow.
This admittedly gave it a different kind of taste... 
I did not even realize this was also in comp.lang.c (thanks, steve, for the
warning!).
Since I had included assembler output for the i386 and also a part of
the SysV/386 man page for 'time' I thought it would be clear what I was talking
about. It was also obvious from the subject line about SCO-UNIX.
It was most interesting to see, how some people declared my included
assembler listing as "irrelevant", thus pushing the topic to a level
of abstraction it was never ment to be. It was EXACTLY for i386 assembler
on a box running UNIX, nothing else.
If you can't find a reason to flame - just create one...
Now everybody is telling me this will not run on an 8086, i286 or some kind
of superprocessor with 124 bit pointers and 12 bit longs. Thanks for the help!
One guy (forgot the name, but he must have been recently out of school, 'cause
he still was arguing with me about his math teacher) even proved it doesn't
work on a PDP11. 
Quite irritating, since nobody claimed it would run on a PDP11.
Nice proof, anyway. My own proof was (only!) for the i386 under ISC-UNIX - 
my fault that I didn't state it loud n'clear enough in my original posting.

One can of course argue about what people think is "good programming
practice", but that's different from saying "you don't know what you are
talking about" or "you fool think your unix box is the center of the
world". At least in my opinion.

So, *please stop* sending me any more hate mail. I'm already enlighted as
a "junior programmer" (this was one of the more modest things I received
by mail; some nice guys hanging around here).

-- 
-----------------------------------------------
L. Hirschbiegel, AEG - A84, Frankfurt (Germany) 
email: unido!aega84!lh     tel: -49-69-66414316  
-----------------------------------------------

gwyn@smoke.brl.mil (Doug Gwyn) (05/25/91)

In article <7649@segue.segue.com> jim@segue.segue.com (Jim Balter) writes:
>In article <1991May22.130713.25852@sco.COM> david@sco.COM (David Fiander) writes:
>>There exist architectures on which the NULL pointer is different from
>>"all bits 0".
>This isn't relevant if using ANSI prototypes, since any form of zero is
>implicitly converted to the appropriate null pointer, no matter how it is
>represented.

Well, no, that's not quite right.  First of all, an appropriate prototype
must be in scope for automatic argument coercions to be performed; second,
only certain ways of writing "zero" will be converted to a null pointer
constant.  The bit pattern is definitely not relevant.

gwyn@smoke.brl.mil (Doug Gwyn) (05/25/91)

In article <384@tmcsys.UUCP> lothar@tmcsys.UUCP (L. Hirschbiegel) writes:
>At least in my opinion.

But the original question clearly indicated an understanding that this
was a portability issue, and it was YOU who decided to turn it into a
386-specific issue and claim that the difference between correct
portable practice and 386-dependent coding "doesn't matter".  It did
matter to the original purpose of the question.  It should also matter
even if you are at the moment programming with the expectation that
the program will run only on a 386, because there is no guarantee that
the non-portable practice will continue to "work" even using future
releases of the "same" C compiler on the "same" hardware platform.
Thus, it would be much wiser to code this properly in the first place,
especially given that it is easy to do so.

In MY opinion, you deserved to be flamed, on several counts.

sef@kithrup.COM (Sean Eric Fagan) (05/25/91)

In article <1991May24.151350.22705@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>Under what architecture is a NULL pointer not "all bits 0"?  

Pr1me, Cyber 180, and another weird machine whose name I forget but might
have been a Burroughs (excuse me, Unisys) machine.

>NULL pointers *are* all zeros, though, since
>casting zero to a pointer must yield a null pointer.  

That is a non-sequitor.  Casting a constant 0 to a pointer must yeild a null
pointer.  Casting an integer, whose value is 0, to a pointer does not
necessarily yield a null pointer.

>(Maybe there's
>a loophole here in ANSI that says that (void *)0 is a null pointer but
>the compiler could implement that casted zero as somthing other than
>a pattern of zeros.  Not likely in the real world.)

ANSI says exactly that.  You should *never* assume that that things are
otherwise.  Talk to Henry, Doug, or Chris about such things; I'll just get
into an argument and end up calling you a fool or worse.  (HGoC might
*think* so, but I don't think they'll *say* so.  Well, actually, I'm not so
sure about that, now that I think about it.)

>You're certainly right that a NULL that produced a virtual memory fault
>upon any use would be better than a virtual zero address.  But it's not
>the "compiler people" who would have to agree to this.  Far too much
>existing code would be broken by a move to this, I'm afraid.

Many, many people have made address 0 result in an address fault (who said
*anything* about virtual memory?  lots of machines don't have virtual
memory, and some of them still manage to compile C).  Some people have made
it work, simply to placate stupid programmer, such as you appear to be.
Frankly, I would *much* rther have my OS complain, so I can track down the
error (for that's what it is) during development.  (SCO, for example, has
address 0 readable and writable, because too many applications people
bitched about it.  I prefer having a core dump, myself.)

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

scs@adam.mit.edu (Steve Summit) (05/25/91)

In article <1991May24.151350.22705@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>Under what architecture is a NULL pointer not "all bits 0"?

Would it be at all possible for anyone who feels the urge to
contribute to this thread to read the comp.lang.c frequently-
asked questions list first, before posting anything more?  (If
you just joined us, this is a *very* old topic, at least for
comp.lang.c, and nothing new is being said.  If comp.unix.sysv386
finds this fascinating, please remove comp.lang.c from the
Newsgroups: line.)

                                            Steve Summit
                                            scs@adam.mit.edu

gwyn@smoke.brl.mil (Doug Gwyn) (05/25/91)

In article <1991May24.151350.22705@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>Under what architecture is a NULL pointer not "all bits 0"?  The problems,
>as many have said, result when a pointer has fewer or more bits than
>an integer (or a long).  NULL pointers *are* all zeros, though, since
>casting zero to a pointer must yield a null pointer.  (Maybe there's
>a loophole here in ANSI that says that (void *)0 is a null pointer but
>the compiler could implement that casted zero as somthing other than
>a pattern of zeros.  Not likely in the real world.)

Please don't post assertions like these when you're not sure of your facts;
it adds confusion, not enlightenment.  Innumerable times in the past in this
newsgroup (and in comp.std.c), correct discussions of this issue have been
posted, and I'm pretty sure it's in the FAQ list.

In fact, in both theory and the real world, null pointers need not be
represented as all zero bit patterns, nor need pointers have the same size
as some integral type, nor need all pointers have the same size.  There
are several C implementations where one or more of those assumptions would
be in error.  Furthermore, these characteristics pose no problem for a
programmer who avoids making such assumptions.

gwyn@smoke.brl.mil (Doug Gwyn) (05/25/91)

In article <1991May25.002706.27552@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>Talk to Henry, Doug, or Chris about such things; I'll just get
>into an argument and end up calling you a fool or worse.  (HGoC might
>*think* so, but I don't think they'll *say* so.  Well, actually, I'm not so
>sure about that, now that I think about it.)

"Sean, you ignorant slut."

I think it's entirely a function of how annoyed we are by hearing the
umpteen-zillionth repetition of the same error, when sources of correct
information are relatively easy to come by.

:-)

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (05/25/91)

In article <383@tmcsys.UUCP>, lothar@tmcsys.UUCP (L. Hirschbiegel) writes:
> In article <1991May22.190908.5311@virtech.uucp> cpcahil@virtech.uucp (Conor P. Cahill) writes:
>> The code you show won't work reliably on systems where the size of a
>> pointer is different from the size of an integer (for ex: large
>> model programs on an 8086 or 80286).

> This was posted to newsgroup "comp.UNIX.SYSV386", right??

It was *also* posted to comp.lang.c.

> Martin was referring to a "time" syscall argument mismatch under
> SCO-UNIX.  I pointed out, that it really makes no difference for the
> argument value itself.  I did NOT say this is a general rule-of-thumb
> for all kinds of cpus and all kinds of compilers?!?!

Then you should have removed comp.lang.c from the Newsgroups: line
before posting.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

allbery@NCoast.ORG (Brandon S. Allbery KF8NH) (05/26/91)

As quoted from <1991May25.002706.27552@kithrup.COM> by sef@kithrup.COM (Sean Eric Fagan):
+---------------
| Many, many people have made address 0 result in an address fault (who said
| *anything* about virtual memory?  lots of machines don't have virtual
| memory, and some of them still manage to compile C).  Some people have made
| it work, simply to placate stupid programmer, such as you appear to be.
| Frankly, I would *much* rther have my OS complain, so I can track down the
| error (for that's what it is) during development.  (SCO, for example, has
| address 0 readable and writable, because too many applications people
| bitched about it.  I prefer having a core dump, myself.)
+---------------

Whatever happened to (System V) ld using a default ld script in /lib?  Plexus
System V did this, and it was trivial to change it from the default to not
mapping page 0 (they even provided a script for this, and a special ld option
that used that script instead; but changing the default script worked fine).

++Brandon
-- 
Me: Brandon S. Allbery			 KF8NH: DC to LIGHT!  [44.70.4.88]
Internet: allbery@NCoast.ORG		 Delphi: ALLBERY
uunet!usenet.ins.cwru.edu!ncoast!allbery

rac@sherpa.UUCP (Roger Cornelius) (05/26/91)

From article <1991May24.044751.5933@virtech.uucp>, by cpcahil@virtech.uucp (Conor P. Cahill):
> lothar@tmcsys.UUCP (L. Hirschbiegel) writes:
> 
>>This was posted to newsgroup "comp.UNIX.SYSV386", right??
> 
> NO.  It was cross-posted to comp.unix.sysv386 AND comp.lang.c

No, the original article, as well as my followup (I posted the code
everyone has been arguing about) were posted only to comp.unix.sysv386.
Some later follow-upper must have done the cross-posting.  Here are
the headers from my post:

Subject: Re: SCO password generator
Newsgroups: comp.unix.sysv386
References: <1991May14.040042.15199@jpradley.jpr.com>

Regardless, of where it was posted, I think everybody now knows that
time(0L) != time((long*)0).  I'm sure I do.  For those interested,
I've included a patch below :-).  Hopefully this will end this thread.

Roger

--- cut here ---

*** a1.c	Sat May 25 16:29:31 1991
--- a2.c	Sat May 25 16:29:58 1991
***************
*** 11,17 ****
  {
  	char word[MAX], hyword[2*MAX];
! 	long seed = time(0L);
  
  	set_auth_parameters(ac,av);
--- 11,17 ----
  {
  	char word[MAX], hyword[2*MAX];
! 	long seed = time((long*)0);
  
  	set_auth_parameters(ac,av);
--- cut here ---

--
Roger Cornelius          rac@sherpa.UUCP         uunet!sherpa!rac

henry@zoo.toronto.edu (Henry Spencer) (05/26/91)

In article <1991May25.002706.27552@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>...Talk to Henry, Doug, or Chris about such things; I'll just get
>into an argument and end up calling you a fool or worse.  (HGoC might
>*think* so, but I don't think they'll *say* so.  Well, actually, I'm not so
>sure about that, now that I think about it.)

Chris is an extremely nice and amazingly patient guy and doesn't say such
things.  Doug and I have our limits. :-)

Actually, the people Len really wants to talk to are the IBM AS/400 people,
whose machine is an exception to almost every naive misconception about C
you have ever seen.  Rumor hath it that if you think "ANSI C *surely* could
have promised XYZ instead of the watered-down version they actually gave us",
there is a high probability that the AS/400 was a major counterexample.
-- 
"We're thinking about upgrading from    | Henry Spencer @ U of Toronto Zoology
SunOS 4.1.1 to SunOS 3.5."              |  henry@zoo.toronto.edu  utzoo!henry

david@sco.COM (David Fiander) (05/27/91)

In article <1991May24.151350.22705@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>
>You're certainly right that a NULL that produced a virtual memory fault
>upon any use would be better than a virtual zero address.  But it's not
>the "compiler people" who would have to agree to this.  Far too much
>existing code would be broken by a move to this, I'm afraid.

No, all I have to do is convince the compiler people.  They don't
particularly care if somebody else's broken code breaks; just ask anybody
that has worked on an optimizer.  Most of the bugs reported against
HCR-PCO (the Portable Code Optimizer) turned out to be bugs in the
application source which worked until an agressive optimizer hacked the
code into something else.

lbr@holos0.uucp (Len Reed) (05/29/91)

In article <1991May25.221530.16119@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:

>Actually, the people Len really wants to talk to are the IBM AS/400 people,
>whose machine is an exception to almost every naive misconception about C
>you have ever seen.

Note: I've dropped the 386 group out of the distribution.

Well, several folks have set my straight on NULL not not necessarily
being all bits zero on some machines.  It is true that (type *)0 must
be the NULL pointer of type, even if done as part of an
implicit cast.  E.g.,

	extern void some_routine(int *);
	....
	some_routine(0);	/* implicit cast here */

Obviously this is not well-coded, even if legal.  I myself always use
NULL instead of zero.

Okay, what about static and global pointers not explicitly initialized?
Older Unices (not sure about the newest) depended upon the kernel's
zeroing out of the BSS to hit global and static data with zeros.  (This
is in some sense a side-effect of zeroing out data for security reasons:
you can peek at what the last process did with the memory you get.)

Are these zero or NULL?  The compiler could catch these and make them
NULL--does it?  Example:

static char *s_ptr;	/* Is s_ptr NULL or all-zeros? */

What about pointers inside structs?  E.g.,

struct my_struct {
	int *pointer;
	int abc;
} instance;

Is instance.pointer NULL or all zeros?

Finally, what if I malloc a my_struct and memset it to zeros?  No way this
can work:
	if (a_ptr = malloc(sizeof(struct my_struct))) != NULL)
	{
	    memset(a_ptr, 0, sizeof(struct my_struct));
	}

There's no way a_ptr->pointer is going to be NULL after this runs since
the compiler can't get this one.  I know that this'll break some of my code.
I use this mechanism for various kinds of linked structures.  If the
static init works (instance.pointer above), I could define a constant
template for initialization and use structure assignment instead of memset:

struct my_struct initer = {NULL, 0};
	or just
struct my_struct initer;	/* trust compiler to init this correctly */

....

	*a_ptr = initer;	/* instead of memset */

But I don't do it now, and I know lots of folks who don't.
-- 
Len Reed
Holos Software, Inc.
Voice: (404) 496-1358
UUCP: ...!gatech!holos0!lbr

sef@kithrup.COM (Sean Eric Fagan) (05/29/91)

In article <1991May28.175246.2160@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>Okay, what about static and global pointers not explicitly initialized?

They are guaranteed to hold the same value as if they had been explicitly
initialized to 0.

>static char *s_ptr;	/* Is s_ptr NULL or all-zeros? */

This is equivalent to

	static char *s_ptr = 0;

>What about pointers inside structs?  E.g.,
>
>struct my_struct {
>	int *pointer;
>	int abc;
>} instance;

I believe that this is equivalent to

	struct my_struct { int *pointer; int abc; } instance = { 0 };

That is, the first element is set to 0.  Which will get treated as NULL for
whatever machine it's compiled for.  (For the vast majority of cases, no
problem, for those that are, they may have several "bss" segments, or some
initialization code that set things up appropriately.)

>Finally, what if I malloc a my_struct and memset it to zeros?  No way this
>can work:

You're right, there is no way it can work.  Which means you can't use
calloc() for some things that used to be done.  What you have to do is, if
you want to be portable, go through and initialize everything yourself,
instead of using a memory-setting routine to do it for you.

>But I don't do it now, and I know lots of folks who don't.

And I know lots of folks who make lots of assumptions about word sizes,
which causes even more problems, or about a writable (or, worse, readable)
location 0.  Doesn't mean it's good practice.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

gwyn@smoke.brl.mil (Doug Gwyn) (05/29/91)

In article <1991May28.175246.2160@holos0.uucp> lbr@holos0.uucp (Len Reed) writes:
>Okay, what about static and global pointers not explicitly initialized?

Before any reference to them, they must somehow be initialized by the
implementation to null pointers of the appropriate types.

>Older Unices (not sure about the newest) depended upon the kernel's
>zeroing out of the BSS to hit global and static data with zeros.

On the PDP-11 and VAX, that was a valid implementation technique.
Note that it also default-initialized floating-point variables to
zero values of the correct types.  Not every environment has such
pleasant properties; in other situations the compiler may have to
emit explicit initialization code (e.g. .ADCON 0xFFFF directives).

>Finally, what if I malloc a my_struct and memset it to zeros?

That properly initializes the integral (sub)members but not
necessarily other basic types.

>But I don't do it now, and I know lots of folks who don't.

Why not?  You should certainly properly set the value of a variable
before trying to use it.

I even write explicit initializers for static objects when the
initial value matters, as an indication that (a) I have thought
about the initial contents and (b) the particular initial value
is necessary for correct operation of the code.

By the way, you may find that your code adapts better, for example
to parallelization, if you initialize using assignment instead of
counting on the static initializer.

gwyn@smoke.brl.mil (Doug Gwyn) (05/29/91)

In article <1991May29.002529.22232@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>That is, the first element is set to 0.

*All* the members of the struct will receive zero or null initializers.

sef@kithrup.COM (Sean Eric Fagan) (05/30/91)

In article <16295@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <1991May29.002529.22232@kithrup.COM> sef@kithrup.COM (Sean Eric Fagan) writes:
>>That is, the first element is set to 0.
>*All* the members of the struct will receive zero or null initializers.

Oops.  I was thinking about unions at the time.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

chap@art-sy.detroit.mi.us (j chapman flack) (06/01/91)

In article <1991May23.040054.23555@Think.COM> barmar@think.com writes:
>No, these systems are not "in common use".  90% of all C programs are
>probably running on 80*86, 680x0, VAX, and SPARC processors, but does that

Mr. Margolin implies that time(0L) is not a problem on the 80*86.

For x > 2, the 80x86 supports two flavors of pointer (near and far) and two
sizes of offset (16 and 32 bit).  The combinations are:

  near, 16:          sizeof(*long) != sizeof(long)
  far,  16:          sizeof(*long) == sizeof(long) BUT null value not all-zero
                                                   in the implementations I
                                                   know of
  far,  32:          sizeof(*long) != sizeof(long)
  near, 32:          sizeof(*long) == sizeof(long) and null value COULD be
                                                   all-zero if the compiler
                                                   implementor felt like it.

So time(0L) *is* incorrect in (at least) 3 out of 4 cases on an 80x86, x > 2.
It's incorrect in *all* cases on earlier 80x86's (though I could imagine an
implementation that used 0x0000:0x0000 as the null pointer; the ones I know
of all use segment:0x0000.)

Of course all my sizeof() comparisons above are based on a 32-bit long, which
is yet another assumption....

I replied to Mr. Evernden by mail before I saw this article.  Sorry for the
duplication.
-- 
Chap Flack                         Their tanks will rust.  Our songs will last.
chap@art-sy.detroit.mi.us                                    -MIKHS 0EODWPAKHS

Nothing I say represents Appropriate Roles for Technology unless I say it does.

andre@targon.UUCP (Andre van Dalen) (06/02/91)

In article <381@tmcsys.UUCP> lh@aega84.UUCP (L. Hirschbiegel) writes:
  >In article <1141@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
  >>In article <588@sherpa.UUCP> rac@sherpa.UUCP (Roger Cornelius) writes:
  >>[...]
  >>>     long seed = time(0L);
  >>                       ^^--------- wrong
  >>                 time((long *)0);
  >>                      ^^^^^^^^^--- right
[ removed assembler listing (gives us a clue :-) ]

  >>Repeat after me: POINTER to long.
  >
  >Repeat after me: IT DOESN'T MATTER :-)

Never worked under MSDOeSn't in different memory models or on 64 bit
machines have you?

-- 
The mail|    AAA         DDDD  It's not the kill, but the thrill of the chase.
demon...|   AA AAvv   vvDD  DD        Ketchup is a vegetable.
hits!.@&|  AAAAAAAvv vvDD  DD                    {nixbur|nixtor}!adalen.via
--more--| AAA   AAAvvvDDDDDD    Andre van Dalen, uunet!hp4nl!targon!andre

sef@kithrup.COM (Sean Eric Fagan) (06/02/91)

In article <9106011048.aa06266@art-sy.detroit.mi.us> chap@art-sy.detroit.mi.us (j chapman flack) writes:
>For x > 2, the 80x86 supports two flavors of pointer (near and far) and two
>sizes of offset (16 and 32 bit).  The combinations are:

Uhm, better go back and reread your manual.  For 808[86] and 80?8[86], there
are two flavours of pointers:  16-bit ("near"), and 32-bit (actually 20 bit
on the '286 and previous), aka "far" in some compilers.

>So time(0L) *is* incorrect in (at least) 3 out of 4 cases on an 80x86, x > 2.

But it won't cause things to fail, except in some very limited cases
(basicly, where one more 16-bit word will cause a stack fault).

>It's incorrect in *all* cases on earlier 80x86's (though I could imagine an
>implementation that used 0x0000:0x0000 as the null pointer; the ones I know
>of all use segment:0x0000.)

Actually, most use segment 0, offset 0, since most people like being able to
use address 0 of an array (yes, the compiler could fudge things, most don't,
though).

>Of course all my sizeof() comparisons above are based on a 32-bit long, which
>is yet another assumption....

long's are guaranteed to be at least 32 bits, as per ANSI C.  Since most
(all?) popular compilers for the iAPX86 architecture (and descendents, of
course) at least claim some measure of ANSI conformance, and 32 bits is
really the only feasible size of a long (other than 16, which defeats the
purpose of a long), you can pretty much rest assured that a long is 32 bits
on an Intel *86 system.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.