From -8338361355864107631
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,bcce9f6c39d8ade1
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 1994-09-21 16:20:53 PST
Newsgroups: comp.std.c++
Path: bga.com!news.sprintlink.net!howland.reston.ans.net!swrinde!sgiblab!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Subject: Re: Some iostream strangeness
Message-ID: <9426404.25042@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU
Organization: Computer Science, University of Melbourne, Australia
References: <1994Sep19.170011.22189@csc.canberra.edu.au> <KANZE.94Sep20183637@slsvhdt.us-es.sel.de>
Date: Tue, 20 Sep 1994 18:43:33 GMT
Lines: 71

kanze@us-es.sel.de (James Kanze US/ESC 60/3/164 #71425) writes:

>tp941821@gum.canberra.edu.au writes:
>
>|> I was looking for some way to read a line, and then discard it.
>|> Here's what I came up with :
>
>|>  cin >> NULL;
>
>|> which doesn't work for obvious reasons;
>
>I suspect that the reasons are anything less than obvious.

Indeed.  When I tried it on using g++ on SunOS, I got a somewhat
suprising *link-time* error message - undefined reference to _strtoul!!!

The reason for this is that (a) I was using g++ 2.5.7, which doesn't
detect the erroroneous initialization of a reference with a non-lvalue
[2.6.0 gets it right] and (b) the SunOS library I was using was the
non-ANSI one, which doesn't include strtoul(), and presumeably
istream::operator>>(int&) is implemented using strtoul().

>|> but then, for curiosity reasons
>|> I tried out :-
>
>|>  cin >> 0;
>
>|> Which surprisingly did the job! which is a bit strange don't you think ?
>|> Any ideas ?? ( used gnu c++ for SunOS ).

I couldn't duplicate this.  I got the same link error described above.
(g++ 2.5.7, SunOS 4.1.3).

>The compiler is broken:-).
>
>|> Is this consistent with the c++ standard ?
>
>No.  But the error (both with NULL and 0) is due to a violation of
>const-ness, and g++ is (or was, I haven't used it lately) notoriously
>lax in this area.

2.6.0 is a lot better.

>Of the two examples, and given the choice of compiler, I am more
>surprised that the first didn't work, than that the second did.  Or
>did Cygnus add Fergus' modification for a real NULL pointer?  (Three
>cheers for them if they did.)

It turned out that g++ already considered `(void *)0' as a null pointer
constant in that it allowed conversion from `(void *)0' to other
pointer types, contrary to the ARM. (Why, I don't know for sure;
perhaps it was an accidental bug).  This meant that there was no need
for __builtin_null_pointer, because you could use `#define NULL (void *)0'.

By another amazing coincidence, at least as of g++/libg++ 2.6, 2.5 and maybe
earlier, <stddef.h> defines NULL as `(void*)0' even for C++. (Again, I
don't think this was deliberate, I suspect it was a purely accidental
bug which was never detected due to the aforementioned bug/feature.)
I think the definition of NULL in the other system header files is the
same as what was in your original C headers.

So with g++, NULL *is* a real null pointer constant - if you
#include <stddef.h> first.  If you #include one of the other header
files that defines NULL first, then it's probably not.

But I still don't see how this explains the behaviour described by
the original poster, since `cin >> (void *)0' should give similar
results to `cin >> 0' anyway.

-- 
Fergus Henderson - fjh@munta.cs.mu.oz.au


