Topic: nullptr == p_one_past_last


Author: kuyper@wizard.net
Date: Mon, 28 Aug 2006 11:34:00 CST
Raw View
"Matthias Hofmann" wrote:
> "Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
> news:JpeIg.13163$j7.326694@news.indigo.ie...
.
> > In the same spirit, if you're working with a two's complement machine
> > which
> > has a 32-Bit long, the "policitically correct" way of setting it to its

More to the point, it's the correct method, political or not.

> > min
> > value is:
> >
> >    long i = -2147483647-1;
>
> Why not assign
>
> long i = -2147483648;
>
> I understand that on a two's complement machine, the bit pattern
> of -2147483648 is the same as that of +2147483648, but shouldn't the sign of
> the integer literal tell the compiler that the value is representable in a
> long, thus preventing undefined behaviour?

The problem is that integer literals do not have signs - check the
grammar. -2147483648 is not an integer literal. It's a unary minus
operator acting on a the integer literal 2147483648. On implementations
where LONG_MAX < 2147483648, that causes problems.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Mon, 28 Aug 2006 17:00:03 GMT
Raw View
kanze posted:

> For that matter, formally: overflow is undefined
> behaviour.


If numeric_limits<int>::modulo is true, then is overflow well-defined? For
instance, does the following code exhibit undefined behaviour?

#include <climits>
#include <limits>

int main()
{
    int i = INT_MAX;

    if (std::numeric_limits<int>::modulo) i *= 5;
}

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Mon, 28 Aug 2006 17:00:20 GMT
Raw View
"Matthias Hofmann" posted:

>>    unsigned i = -1;
>>    size_t i = -1;
>>    long unsigned i = -1;
>
> I often used that method in practice, but I did not know that the
> standard guarantees that it works. Is there an explicit statement, or is
> this behaviour concluded from certain other requirements?


It's guaranteed to work -- something to do with modulo arithmetic.


>>    long i = -2147483647-1;
>
> Why not assign
>
> long i = -2147483648;
>
> I understand that on a two's complement machine, the bit pattern
> of -2147483648 is the same as that of +2147483648, but shouldn't the
> sign of the integer literal tell the compiler that the value is
> representable in a long, thus preventing undefined behaviour?


Where you have:

    -2147483648

, it's interpreted as:

    - (2147483648)

, i.e. the unary negation operator is applied to a positive integer
literal. The positive integer literal 2147483648 is out of range, and thus
the code is ill-formed.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Tue, 29 Aug 2006 09:21:45 CST
Raw View
Frederick Gotham wrote:
> kanze posted:

> > For that matter, formally: overflow is undefined
> > behaviour.

> If numeric_limits<int>::modulo is true, then is overflow
> well-defined?

That's a very good question.  All the standard seems to say is
that "a type is modulo if it is possible to add two positive
numbers and have a result that wraps around to a third number
that is less."  (Less than what: the real result, or one of the
original two numbers?)  I'm not sure what the formal definition
of "wraps" is: would an implementation which always gave a
result of 0 on overflow be "modulo".  (I suspect that the intent
is that the results be well defined on a specific machine.  And
that the results would be what one normally expects by "wrap".)

> For instance, does the following code exhibit
> undefined behaviour?

> #include <climits>
> #include <limits>

> int main()
> {
>     int i = INT_MAX;

>     if (std::numeric_limits<int>::modulo) i *= 5;
> }

Again, who knows?  I would say yes, on the grounds that you can
have hardware which wraps for add and subtract, but generates a
trap for multiply and divide.

Personally, I find the current definition a bit useless: to be
useful, you'd need a finer definition of "wraps", and you'd need
to specify that it applies to all arithmetic operands (including
unary minus!).  Or you can say that it should only be true if
the implementation specifies (and guarantees) what it means.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Tue, 29 Aug 2006 15:45:54 GMT
Raw View
<kuyper@wizard.net> schrieb im Newsbeitrag
news:1156780076.100410.22760@74g2000cwt.googlegroups.com...

>> I understand that on a two's complement machine, the bit pattern
>> of -2147483648 is the same as that of +2147483648, but shouldn't the sign
>> of
>> the integer literal tell the compiler that the value is representable in
>> a
>> long, thus preventing undefined behaviour?
>
> The problem is that integer literals do not have signs - check the
> grammar. -2147483648 is not an integer literal. It's a unary minus
> operator acting on a the integer literal 2147483648. On implementations
> where LONG_MAX < 2147483648, that causes problems.

As far as I understand, it causes problems on any two's complement machine,
as then the absolute value of the minimum of an integer is always one more
than its maximum. According to what you have just told me about interger
literals having no sign, the following assignment does also yield undefined
behaviour, doesn't it?

int i = INT_MIN;

Or at least the INT_MIN makro cannot simply be implemented as

#define INT_MIN -2147483648

It must be something like

const int INT_MIN = -2147483647-1;

But then it wouldn't be a makro anymore, which I don't know is a
requirement.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Tue, 29 Aug 2006 12:08:41 CST
Raw View
"Matthias Hofmann" wrote:
> <kuyper@wizard.net> schrieb im Newsbeitrag
> news:1156780076.100410.22760@74g2000cwt.googlegroups.com...
>
> >> I understand that on a two's complement machine, the bit pattern
> >> of -2147483648 is the same as that of +2147483648, but shouldn't the sign
> >> of
> >> the integer literal tell the compiler that the value is representable in
> >> a
> >> long, thus preventing undefined behaviour?
> >
> > The problem is that integer literals do not have signs - check the
> > grammar. -2147483648 is not an integer literal. It's a unary minus
> > operator acting on a the integer literal 2147483648. On implementations
> > where LONG_MAX < 2147483648, that causes problems.
>
> As far as I understand, it causes problems on any two's complement machine,
> as then the absolute value of the minimum of an integer is always one more
> than its maximum. According to what you have just told me about interger
> literals having no sign, the following assignment does also yield undefined
> behaviour, doesn't it?
>
> int i = INT_MIN;

No, it's not allowed to have undefined behavior. It's up to the
implementation to define INT_MIN in a fashion that will make that work.

> Or at least the INT_MIN makro cannot simply be implemented as
>
> #define INT_MIN -2147483648

Correct. Not only is the integer literal illegal, but the fact that
there's no parenthesis around the definition is also a problem.
Parentheses aren't needed around integer literals, but in general they
are needed around macros that expand into expressions, in order to
prevent those macros from being misinterpreted in the context of other
operators.

> It must be something like
>
> const int INT_MIN = -2147483647-1;
>
> But then it wouldn't be a makro anymore, which I don't know is a
> requirement.

It is a requirement. The simplest solution is also the most popular:

#define INT_MIN (-214783647-1)
or
#define INT_MIN (-INT_MAX - 1)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: clarkcox3@gmail.com ("Clark S. Cox III")
Date: Tue, 29 Aug 2006 19:13:42 GMT
Raw View
Matthias Hofmann wrote:
> <kuyper@wizard.net> schrieb im Newsbeitrag
> news:1156780076.100410.22760@74g2000cwt.googlegroups.com...
>
>>> I understand that on a two's complement machine, the bit pattern
>>> of -2147483648 is the same as that of +2147483648, but shouldn't the sign
>>> of
>>> the integer literal tell the compiler that the value is representable in
>>> a
>>> long, thus preventing undefined behaviour?
>> The problem is that integer literals do not have signs - check the
>> grammar. -2147483648 is not an integer literal. It's a unary minus
>> operator acting on a the integer literal 2147483648. On implementations
>> where LONG_MAX < 2147483648, that causes problems.
>
> As far as I understand, it causes problems on any two's complement machine,
> as then the absolute value of the minimum of an integer is always one more
> than its maximum. According to what you have just told me about interger
> literals having no sign, the following assignment does also yield undefined
> behaviour, doesn't it?
>
> int i = INT_MIN;

No it does not yield undefined behavior.

> Or at least the INT_MIN makro cannot simply be implemented as
>
> #define INT_MIN -2147483648

Correct, as that is attempting to negate the positive value
(2147483648), which cannot be represented on such a machine without
promoting it to another type (which may not be possible if long has the
same limits as int).

> It must be something like
>
> const int INT_MIN = -2147483647-1;
>
> But then it wouldn't be a makro anymore, which I don't know is a
> requirement.

#define INT_MIN (-2147483647-1)

--
Clark S. Cox III
clarkcox3@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Fri, 25 Aug 2006 16:03:26 GMT
Raw View
kanze posted:

> The point is that something like (int)(unsigned)(-1) has an
> implementation defined result, AND that result can include
> raising a signal.


If you want to be sure that the following is legal:

    (int)(unsigned)-1

Then maybe try:

    COMPASS( numeric_limits<int>::modulo );

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Sat, 26 Aug 2006 20:29:50 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:k6FHg.13109$j7.326537@news.indigo.ie...
> kanze posted:
>
>> The point is that something like (int)(unsigned)(-1) has an
>> implementation defined result, AND that result can include
>> raising a signal.
>
>
> If you want to be sure that the following is legal:
>
>    (int)(unsigned)-1
>
> Then maybe try:
>
>    COMPASS( numeric_limits<int>::modulo );

A value of -1 cannot be represented in an unsigned, no matter whether int is
modulo or not.

Talking about value representation: It just occurred to me that according to
3.9.1, there seems to be no guarantee that an int can actually hold a value
of -1. There is not even a guarantee that a signed integer type can hold
negative values at all, only that "The range of nonnegative values of a
signed integer type is a subrange of the corresponding unsigned integer type
[...]".

In section 2.13.1 the standard says that the type of an integer literal
without a suffix is either int or long int, depending on how many bits are
rquired to represent the value. If it does not even fit into a long int, the
behaviour is undefined. But how am I supposed to write portable code if
there is no guarantee that

int i = -1000;

does not yield undefined behaviour?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 27 Aug 2006 17:03:20 GMT
Raw View
In article <4lb062F132bmU1@individual.net>, Matthias Hofmann
<hofmann@anvil-soft.com> writes
>
>A value of -1 cannot be represented in an unsigned, no matter whether int is
>modulo or not.

Well for unsigned there is a requirement that it is represented by the
largest value provided for the unsigned range.

>
>Talking about value representation: It just occurred to me that according to
>3.9.1, there seems to be no guarantee that an int can actually hold a value
>of -1. There is not even a guarantee that a signed integer type can hold
>negative values at all, only that "The range of nonnegative values of a
>signed integer type is a subrange of the corresponding unsigned integer type
>[...]".

That is in addition to the requirements specified by numeric_limits and
though the C++ Standard does not specify the minimal limits it does also
require that climits (limits.h) be supported for C compatibility and I
find it hard to envision how that would work if the minimal ranges for
fundamental types were not at least those required by C.

>
>In section 2.13.1 the standard says that the type of an integer literal
>without a suffix is either int or long int, depending on how many bits are
>rquired to represent the value. If it does not even fit into a long int, the
>behaviour is undefined. But how am I supposed to write portable code if
>there is no guarantee that
>
>int i = -1000;
>
>does not yield undefined behaviour?

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sun, 27 Aug 2006 17:05:53 GMT
Raw View
"Matthias Hofmann" posted:

>> If you want to be sure that the following is legal:
>>
>>    (int)(unsigned)-1
>>
>> Then maybe try:
>>
>>    COMPASS( numeric_limits<int>::modulo );
>
> A value of -1 cannot be represented in an unsigned, no matter whether
> int is modulo or not.


Assigning -1 to an unsigned integer is a common method of setting it to its
greatest value:

    unsigned i = -1;
    size_t i = -1;
    long unsigned i = -1;


> Talking about value representation: It just occurred to me that
> according to 3.9.1, there seems to be no guarantee that an int can
> actually hold a value of -1.
> There is not even a guarantee that a signed integer type can hold
> negative values at all, only that "The range of nonnegative values of a
> signed integer type is a subrange of the corresponding unsigned integer
> type [...]".


The Standard guarantees a minimum range for "int":

    -32767 through 32767


> In section 2.13.1 the standard says that the type of an integer literal
> without a suffix is either int or long int, depending on how many bits
> are rquired to represent the value.


Or "long long int" if it's really big. ("long long int" is being phased
in.)


> If it does not even fit into a long int, the behaviour is undefined.


Indeed. The following line of code is non-portable:

    long unsigned i = 4294967295;

, while the following is perfectly portable:

    long unsigned i = 4294967295U;

In the same spirit, if you're working with a two's complement machine which
has a 32-Bit long, the "policitically correct" way of setting it to its min
value is:

    long i = -2147483647-1;


> But how am I supposed to write portable code if there is no guarantee
> that
>
> int i = -1000;
>
> does not yield undefined behaviour?


That definitely won't invoke undefined behaviour, because -1000 is
guaranteed to be within range.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Mon, 28 Aug 2006 14:06:05 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:JpeIg.13163$j7.326694@news.indigo.ie...

> Assigning -1 to an unsigned integer is a common method of setting it to
> its
> greatest value:
>
>    unsigned i = -1;
>    size_t i = -1;
>    long unsigned i = -1;

I often used that method in practice, but I did not know that the standard
guarantees that it works. Is there an explicit statement, or is this
behaviour concluded from certain other requirements?

> The Standard guarantees a minimum range for "int":
>
>    -32767 through 32767

That's good news! :-) I was already getting worried about the integer
literals in my code...

> In the same spirit, if you're working with a two's complement machine
> which
> has a 32-Bit long, the "policitically correct" way of setting it to its
> min
> value is:
>
>    long i = -2147483647-1;

Why not assign

long i = -2147483648;

I understand that on a two's complement machine, the bit pattern
of -2147483648 is the same as that of +2147483648, but shouldn't the sign of
the integer literal tell the compiler that the value is representable in a
long, thus preventing undefined behaviour?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Mon, 28 Aug 2006 09:02:17 CST
Raw View
Francis Glassborow wrote:
> In article <4lb062F132bmU1@individual.net>, Matthias Hofmann
> <hofmann@anvil-soft.com> writes
> >
> >A value of -1 cannot be represented in an unsigned, no matter whether int is
> >modulo or not.
>
> Well for unsigned there is a requirement that it is represented by the
> largest value provided for the unsigned range.

No. There's a requirement that a value of -1, if converted to an
unsigned type, results in the largest value of that type. But that
value doesn't represent -1; it doesn't represent anything - it's
represented by a bit pattern, and that bit pattern doesn't represent
-1, it represents the largest value of that type.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Mon, 28 Aug 2006 09:40:04 CST
Raw View
"Matthias Hofmann" wrote:
> "Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
> news:k6FHg.13109$j7.326537@news.indigo.ie...
> > kanze posted:

> >> The point is that something like (int)(unsigned)(-1) has an
> >> implementation defined result, AND that result can include
> >> raising a signal.

> > If you want to be sure that the following is legal:

> >    (int)(unsigned)-1

> > Then maybe try:

> >    COMPASS( numeric_limits<int>::modulo );

> A value of -1 cannot be represented in an unsigned, no matter
> whether int is modulo or not.

No, but the value of converting -1 to unsigned is well defined,
by the standard.  The problem is converting the resulting value
back to an int; that is implementation defined.  But I'm not
sure that numeric_limits<int>::modulo specifies what I want.
According to the standard, it should be true "if it is possible
to add two positive numbers and have a result that wraps around
to a third number that is less."  On a one's complement, this
could also be true, but it still doesn't guarantee that the
conversion unsigned to int doesn't result in a different bit
pattern.  For that matter, formally: overflow is undefined
behaviour, conversion from int to unsigned implementation
defined.  One could thus imagine an implementation which checked
during the conversion, and generated a signal, but just let the
hardware do its thing for overflow.

> Talking about value representation: It just occurred to me
> that according to 3.9.1, there seems to be no guarantee that
> an int can actually hold a value of -1.

The header <climits> is part of C++.  It is defined by reference
to the C standard.  And the C standard says that INT_MIN must be
at most -32767.

> There is not even a guarantee that a signed integer type can
> hold negative values at all, only that "The range of
> nonnegative values of a signed integer type is a subrange of
> the corresponding unsigned integer type [...]".

> In section 2.13.1 the standard says that the type of an
> integer literal without a suffix is either int or long int,
> depending on how many bits are rquired to represent the value.
> If it does not even fit into a long int, the behaviour is
> undefined. But how am I supposed to write portable code if
> there is no guarantee that

> int i = -1000;

> does not yield undefined behaviour?

That works.  On the other hand, try writing LONG_MIN for a 32
bit 2's complement machine.  The value should be -2147483648,
but you cannot write that (and the results of doing so are
undefined behavior).

In practice, of course, we always count on the compiler giving
us a little more than the strict minimum required by the
standard: there's no guarantee that the stack will be large
enough to call even a single function, and exceeding resource
limits is undefined behavior too.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Tue, 22 Aug 2006 22:32:35 CST
Raw View
Frederick Gotham wrote:
> Greg Herlihy posted:

> > A C++ program may not be very portable, but C++ the language
> > is.

> Ridiculous! It's quite easy to keep one's code, and thus one's
> program, portable.

It depends on what you are doing.  What is quite easy is keeping
the non-portable parts in small, isolated modules so you can
port them as needed, without modifying the rest.

> > And given the computing landscape of the 70s in which C grew
> > up - this calculation makes perfect sense: the prospect of
> > running one program on even more than a single machine (much
> > less, two different kinds of machines) no doubt seemed to
> > have far less practical value than the prospect of using a
> > single computer language to write programs on different
> > types of computers.

> All my code is fully portable. All of it.

So you've never written anything but a toy program.  Never used
a GUI, never written anything threaded, never used a socket.
Never been concerned by performance, and had to profile a
program.  Never done anything with a filename but copy it.
Never needed options from the command line.

I've done all of these at one time or another, and I don't think
I've ever written anything but the simplest programs which
didn't do at least one of them, generally many of the them.

> > So the word "portable" when describing C++ really refers to
> > the language's portability - and not to the portability of
> > its source code.  Consequently, if the ability to program in
> > C++ across a diverse set of computing hardware is one's
> > definition of "portable" than, yes, C++ is portable. If  on
> > the other hand, the portability of a computer language is
> > measured in terms of how easily and reliabily a single
> > program can made to run on a diverse set of computer
> > hardware, then "portable C++ code" would be an oxymoron.

> No, not all. I am aware of the restrictions and freedoms which
> an implementation of C++ may have. With this knowledge, I can
> write fully- portable, Standard-compliant code.

How do you start a thread?  How do you synchronize a write to
disk?  How do you listen on a socket?  How do you parse
filenames, to handle a directory tree?

My current application needs all of these.  Which means that it
cannot be written in 100% portable C++.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Tue, 22 Aug 2006 22:31:41 CST
Raw View
Keith Thompson wrote:
> "kanze" <kanze@gabi-soft.fr> writes:
> [...]
> > Historically, I've always thought that the solution involved a
> > grill, with four mutually exclusive categories: invalid
> > pointers, null pointers, pointers to an object, and pointers one
> > past the end.
> [...]

> Except that a pointer just past the end of an object can also
> be a pointer to another object, if the two objects happen to
> be adjacent in memory.  (Obviously in that case the
> just-past-the-end pointer cannot be null.)

I know.  That complicates things a little, but not really too
much.  Conceptually, the pointer is one or the other, and if, in
your grill, you ensure that the results are unspecified when
comparing one or the other, it ends up that you can ignore the
problem.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 23 Aug 2006 03:42:23 GMT
Raw View
Matthias Hofmann posted:

> Source code portability usually ends as soon as you are calling a function
> from the Windows API. Or XWindows, Gnome, KDE, MFC, DirectX... In C++, its
> easy to write portable code, but hard to write portable programs.


There are portable GUI packages, portable graphics packages, etc.. Use them
and you shouldn't have a problem.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 23 Aug 2006 03:42:45 GMT
Raw View
SuperKoko posted:

> Also, sometimes you can rely on implementation-defined things if
> they're widely available and all of your target platforms include this
> implementation-defined thing (for example CHAR_BIT==8 is widely
> available).
> Of course, it's always better not to rely on that.


I'd expect a compile-time assertion:

    COMPASS(8 == CHAR_BIT);

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Wed, 23 Aug 2006 04:58:48 GMT
Raw View
<kuyper@wizard.net> schrieb im Newsbeitrag
news:1156214531.151439.218280@75g2000cwc.googlegroups.com...
> "Matthias Hofmann" wrote:
>> "Earl Purple" <earlpurple@gmail.com> schrieb im Newsbeitrag
>> news:1156085807.163658.255070@i3g2000cwc.googlegroups.com...
> .
>> > yes, that is exactly what I'm referring to. An iterator can be
>> > implemented as a pointer, with the end() iterator being "one past the
>> > end". In the case of an empty sequence, you may well use a NULL pointer
>> > to store the result of both begin() and end().
>>
>> But the wording of 5.7/3 seems to imply that the end() iterator cannot be
>> a
>> NULL pointer.
>
> Are you sure you're citing the right section? I don't see a connection
> between 5.7/3 and this subject; it's just defines the operators + and -
> as returning the sum and difference, respectively, of their operands.
> That's meaningful for arithmetic types, but useless for pointer types,
> where "sum" and "difference" have no intrinsic meaning; but either way,
> it doesn't seem relevant to end() and NULL.

My mistake, the wording I was talking about is in section 5.7/5: "[...] if
the expression Q points one past the last element of an array object, the
expression (Q) - 1 points to the last element of the array object".

Obviously, this does not work for NULL as the end() iterator, unless the
last element of the array is located at:

static_cast<ELEMENT_TYPE*>( NULL ) - 1

However, I am just realizing that this section does not give any guarantee
for empty sequences, so it does in fact *not* imply that the end() iterator
cannot be NULL.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Wed, 23 Aug 2006 09:39:50 CST
Raw View
Frederick Gotham wrote:
> Matthias Hofmann posted:
>
> > Source code portability usually ends as soon as you are calling a function
> > from the Windows API. Or XWindows, Gnome, KDE, MFC, DirectX... In C++, its
> > easy to write portable code, but hard to write portable programs.
>
>
> There are portable GUI packages, portable graphics packages, etc.. Use them
> and you shouldn't have a problem.

I'd be very surprised to see any such package being portable to all
confiorming implementations of C++, given that some of those
implementations are for systems where it's not even possible to
implement a GUI. Of course, the package could be set up so that when
installed on such a system, any attempt to actually use it has either
no visible result, or returns an error indication of some kind, but I
would not consider that a successful port of that package to that
system.

Howver, even to the extent that such packages are portable, there is
still non-portable code; it's just part of those packages, rather than
being explicitly part of your program.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Wed, 23 Aug 2006 09:39:10 CST
Raw View
"Matthias Hofmann" wrote:
.
> My mistake, the wording I was talking about is in section 5.7/5: "[...] if
> the expression Q points one past the last element of an array object, the
> expression (Q) - 1 points to the last element of the array object".
>
> Obviously, this does not work for NULL as the end() iterator, unless the
> last element of the array is located at:
>
> static_cast<ELEMENT_TYPE*>( NULL ) - 1

Yes, that is precisely the situation that is being discussed. An
implementation is allowed to use a pointer representing a specific
memory address as a null pointer, so long as no object accessible to
user code occupies that memory location, and most implementations do
precisely that. While the expression you give has undefined behavior,
an implementation is free to handle it like any other pointer-integer
expression, with the result that it points at a position
sizeof(ELEMENT_TYPE) before the one reserved for the null pointer value
of that type. For such an implementation, the question we're discussing
is equivalent to asking whether it is prohibited from allocating a
user-accessible object of ELEMENT_TYPE in that location.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 23 Aug 2006 09:34:44 CST
Raw View
Frederick Gotham wrote:
> SuperKoko posted:

> > Also, sometimes you can rely on implementation-defined things if
> > they're widely available and all of your target platforms include this
> > implementation-defined thing (for example CHAR_BIT==8 is widely
> > available).
> > Of course, it's always better not to rely on that.

> I'd expect a compile-time assertion:

>     COMPASS(8 == CHAR_BIT);

It's not unusual to have something like:

    #include <limits.h>
    #if CHAR_BIT != 8
    #error Requires 8 bit chars
    #endif

at the head of a translation unit.  But you do you insist that
the signed integral types are 2's complement?  (INT_MIN !=
-INT_MAX, maybe?)  Or that converting an unsigned int to a
signed int won't trap or generate a signal, and that the mapping
is a bijection (i.e. that integer types are 2's complement, and
that the conversion from an unsigned to a signed simply takes
the bits as they are, without changing anything)?

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 23 Aug 2006 16:14:16 GMT
Raw View
kanze posted:

> But you do you insist that
> the signed integral types are 2's complement?  (INT_MIN !=
> -INT_MAX, maybe?)


Something like:

    COMPASS( 3 == (-1 & 3) ); /* Must be two's complement */


> Or that converting an unsigned int to a signed int won't trap or
> generate a signal, and that the mapping is a bijection (i.e. that
> integer types are 2's complement, and that the conversion from an
> unsigned to a signed simply takes the bits as they are, without changing
> anything)?


A combinations of checks, things like:

    COMPASS( numeric_limits<int>::digits + 1
             == numeric_limits<unsigned>::digits );

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 23 Aug 2006 21:05:53 CST
Raw View
Frederick Gotham wrote:
> kanze posted:

> > But you do you insist that
> > the signed integral types are 2's complement?  (INT_MIN !=
> > -INT_MAX, maybe?)

> Something like:

>     COMPASS( 3 == (-1 & 3) ); /* Must be two's complement */

Clever.

> > Or that converting an unsigned int to a signed int won't trap or
> > generate a signal, and that the mapping is a bijection (i.e. that
> > integer types are 2's complement, and that the conversion from an
> > unsigned to a signed simply takes the bits as they are, without changing
> > anything)?

> A combinations of checks, things like:

>     COMPASS( numeric_limits<int>::digits + 1
>              == numeric_limits<unsigned>::digits );

How does that guarantee that the conversion takes the bits as
they are?  One legal implementation of converting unsigned to
int would be to convert any value out of range to a constant
value (INT_MAX, for example).  Another would be to generate an
implementation defined signal if the value was out of range.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Thu, 24 Aug 2006 10:20:24 CST
Raw View
kuyper@wizard.net wrote:
> Frederick Gotham wrote:
> > Matthias Hofmann posted:
> >
> > > Source code portability usually ends as soon as you are calling a function
> > > from the Windows API. Or XWindows, Gnome, KDE, MFC, DirectX... In C++, its
> > > easy to write portable code, but hard to write portable programs.
> >
> >
> > There are portable GUI packages, portable graphics packages, etc.. Use them
> > and you shouldn't have a problem.
>
> I'd be very surprised to see any such package being portable to all
> confiorming implementations of C++, given that some of those
> implementations are for systems where it's not even possible to
> implement a GUI.
No, but some of those libraries (wxWidgets) are almost as portable as
they can be (i.e. it turns on all almost all platforms having a GUI).
In fact, wxWidgets is probably more available than well-compliant ISO
C++98 implementations (I mean implementations supporting member
templates, optional template parameters, namespaces, the STL,
exceptions, etc.).

>  Of course, the package could be set up so that when
> installed on such a system, any attempt to actually use it has either
> no visible result, or returns an error indication of some kind, but I
> would not consider that a successful port of that package to that
> system.
>
Yes, of course.

> Howver, even to the extent that such packages are portable, there is
> still non-portable code; it's just part of those packages, rather than
> being explicitly part of your program.
>
That's not an argument!
Of course there is non portable code (perhaps not in code in C++
language but in C, assembly Fortran or whatever)!
But even if this was built in the C++ language as standard C++ library
or as core language features there would still be non-portable code
behind! That's not a problem!
And even if all OS were using X-Window there is still non-portable code
at the device drivers level!

Even languages having a builtin GUI contain non-portable code ... at
the language implementation level!
Moreover I highly doubt that there is any such language available on
more platforms than wxWidgets itself.
However it might possible (it's not even sure) that if C++0x contains a
GUI, it'll rapidly spread on more platforms than wxWidgets.

If a GUI was added as a mandatory element of C++0x, on platforms that
really have no GUI, I think that nobody would implement a fully
compliant C++0x compiler... They would probably only implement C++98 or
at best a partial implementation of C++0x missing the GUI.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 24 Aug 2006 16:33:49 GMT
Raw View
kanze posted:

>>     COMPASS( 3 == (-1 & 3) ); /* Must be two's complement */
>
> Clever.


    ; )


>> A combinations of checks, things like:
>
>>     COMPASS( numeric_limits<int>::digits + 1
>>              == numeric_limits<unsigned>::digits );
>
> How does that guarantee that the conversion takes the bits as
> they are?  One legal implementation of converting unsigned to
> int would be to convert any value out of range to a constant
> value (INT_MAX, for example).  Another would be to generate an
> implementation defined signal if the value was out of range.


Maybe...

Take two objects, one signed, one unsigned, and then compare them by using
arrays of unsigned char?

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Fri, 25 Aug 2006 09:50:26 CST
Raw View
Frederick Gotham wrote:
> kanze posted:
> >> A combinations of checks, things like:

> >>     COMPASS( numeric_limits<int>::digits + 1
> >>              == numeric_limits<unsigned>::digits );

> > How does that guarantee that the conversion takes the bits as
> > they are?  One legal implementation of converting unsigned to
> > int would be to convert any value out of range to a constant
> > value (INT_MAX, for example).  Another would be to generate an
> > implementation defined signal if the value was out of range.

> Maybe...

> Take two objects, one signed, one unsigned, and then compare
> them by using arrays of unsigned char?

What does that tell us?  We already know that for values
representable in both types, the representation is the
same---the standard requires it.  And we cannot initialize the
two objects with the same value if the value is not
representable in one of the types.

The point is that something like (int)(unsigned)(-1) has an
implementation defined result, AND that result can include
raising a signal.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "ThosRTanner" <ttanner2@bloomberg.net>
Date: Mon, 21 Aug 2006 05:04:29 CST
Raw View
Maciej Sobczak wrote:
> ThosRTanner wrote:
>
> > I don't think 4.10/1 is achievable then. The general idea of a virtual
> > machine is that all memory addresses are accessible.
>
> But C++ is not forced to use all of them.
> The implementation is allowed to explicitly allocate more than is needed
> to accommodate the past-the-end pointer value.
> Such an implementation will never allocate anything starting at
> 0xffffffff, even if you ask for an array of 1 byte - exactly to ensure
> the room for that additional past-the-end address.
 Ah, forgot that. Mind you, it's still a potential problem on embedded
systems where magic data validly lives at address -1 (you can't malloc
it, but you can still have a valid pointer to it, which can be
incremented to 0). In which case I suppose you have to go the route of
saying "the null pointer has a value of ..." [which could possibly be
link time generated]. Makes life a bit hard for the compiler though.
implicit pointer casts to bool haved to be turned into (a != nullptr).
Comparisons of pointers with 0 will have to be detected and changed.
And as for those bits of code that indulge themselves in this:
     ptr *p;
    int q = (int)p;
   if (q != 0)

Well, I suppose they deserve what they get.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Mon, 21 Aug 2006 05:06:56 CST
Raw View
Frederick Gotham wrote:
> posted:
>
> > Frederick Gotham wrote:
> >> SuperKoko posted:
> >>
> >>
> >> >>     (1) A pointer to one past the last element of an array shall not
> >> >>     be a
> >> >> null pointer.
> >> >>
> >> >> or:
> >> >>
> >> >>     (2) This Standard imposes no restriction whereby a pointer to
> >> >>     one past
> >> >> the last element of an array shall not be a null pointer.
> >> >>
> >> >> Something like that.
> >> >>
> >> > Or, a third possibility:
> >> > (3) It is implementation-defined whether a pointer to one past the
> >> > last element of an array can be a null pointer.
> >>
> >>
> >> That's exactly the same as number (2), because it permits an
> >> implementation to have a "one past last" pointer which is null.
> >
> > Not true. If it's implementation-defined, an implmentation is required
> > to document whether or not it has chosen to allow this possibility.
> > Option 2 imposes no such requirement.
>
>
> Nonetheless, it allows the possiblity, and so we must take this into
> account when writing portable code. The following function is broken if a
> pointer to "one past last" can be null:
>
> void ProcessArray(char unsigned const *p1, char unsigned const *p2)
> {
>     if (!p) return ProcessNullTerminatedArray(p1);
>
>     do
>     {
>         *p++ *= 5;
>     } while(p1 != p2);
> }
>
I didn't said it was a good idea.
For the sake of completness I said that it was a possible normative
statement clarifying the issue as your two satements didn't included
this case.

Also, sometimes you can rely on implementation-defined things if
they're widely available and all of your target platforms include this
implementation-defined thing (for example CHAR_BIT==8 is widely
available).
Of course, it's always better not to rely on that.

I think that the best solution would be to explicitly state that a
pointer to an object or to one past the end of an array can never be
NULL....

Then, a platform where there is actually, an array containing useful
data, just "before/under" the NULL pointer, would allow users to access
this data through non-portable specific means... But, to remain
standard, this compiler would never allocate memory (automatic
variables, static-storage variables, heap, or memory produced by any
other "standard facility") at this place.

In that case, instead of trying to complicate the wording of the
standard itself, it's better to complicate the wording of documentation
of such compilers which would contain something like:

You can get a sort-of pointer to this special array (containing special
data) through this special non-portable mechanism, but this sort of
pointer doesn't follow exactly the rules of "pointers" of the ISO
standard, in fact, this pointer behave exactly like a standard pointer
except that a pointer one past last element of this array is (or can
be) NULL.

In that case:

It's easy to write 100% portable code.
It's still possible to write non-portable code on platforms where there
are useful things near the NULL pointer.
The standard would be simple and clear about this issue.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Mon, 21 Aug 2006 15:06:15 GMT
Raw View
"Earl Purple" <earlpurple@gmail.com> schrieb im Newsbeitrag
news:1156085807.163658.255070@i3g2000cwc.googlegroups.com...
>
>> How do you get a pointer to an empty sequence? Unless you are talking of
>> iterators in the sense of the STL...
>>
> yes, that is exactly what I'm referring to. An iterator can be
> implemented as a pointer, with the end() iterator being "one past the
> end". In the case of an empty sequence, you may well use a NULL pointer
> to store the result of both begin() and end().

But the wording of 5.7/3 seems to imply that the end() iterator cannot be a
NULL pointer.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Mon, 21 Aug 2006 10:08:33 CST
Raw View
Matthias Hofmann wrote:
> "SuperKoko" <tabkannaz@yahoo.fr> schrieb im Newsbeitrag
> news:1156071550.941088.290450@m73g2000cwd.googlegroups.com...

> > "Matthias Hofmann" wrote:
> >> char arr[] = "Hello";
> >> int i = sizeof arr / sizeof arr[0];
> >> char* p = &arr[i];

> >> The point is that in the last line, a pointer one past the
> >> end of the array is dereferenced in order to take the
> >> address of the 'object' it points to.  If I remember
> >> correctly, there is an exception in the C standard that
> >> makes this legal, while it is undefined behaviour in C++.

> > No. Applying the unary * operator doesn't create UB (you can
> > read the expr.unary.op) However an lvalue-to-rvalue
> > conversion done on such lvalue or an assignment of such
> > lvalue has UB.

> So it is not undefined behaviour to code like this?

> char a[10];
> char* p = &a[10]

It depends on which section of the standard you read.

Historically, in C90, it was undefined behavior (intentionally
or not).  The earliest interpretations of C++ supposed that this
was unchanged in C++, that because C++ didn't have the explicit
escape clause that C99 added, it was undefined behavior.  Since
then, it would seem that changes in the way C++ worded the
requirements of C90 mean that it might be defined in C++ after
all.  As far as I can tell, none of these changes had the intent
of giving a different result than what was expressed in C90, but
of course, most of them took place before the fact that the
expression had undefined behavior in C90 was realized.  The
wording is again being modified in C++0x, and from what I
understand, it will allow such expressions, explicitly and
intentionally.

Logically, I'd say that it should stay undefined.  But
pratically, all compilers allow it, and people use it.  So what
we probably need is something the lines of "If an lvalue
designates an element one past the end of an array, an lvalue to
rvalue conversion, trying to modify the lvalue, or calling a
member function on it, results in undefined behavior."  It's a
lot more wording than simply saying that dereferencing a pointer
one past the end is undefined behavior, but it does bring the
standard more in line with reality, which isn't a bad thing
either.

> > Unfortunately, the term "dereferencing the null pointer" is
> > currently abusively used in the ISO standard as being UB.
> > There is an active issue about that.
> > http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#232

> This sounds like the standard says it is not undefined
> behaviour, but there is ongoing discussion about whether this
> should be changed?

Well, there's an ongoing discussion because the standard lists
it as undefined behavior in one place, but doesn't seem to
unambiguously define it as such elsewhere.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: clarkcox3@gmail.com ("Clark S. Cox III")
Date: Mon, 21 Aug 2006 16:09:48 GMT
Raw View
Matthias Hofmann wrote:
> "Earl Purple" <earlpurple@gmail.com> schrieb im Newsbeitrag
> news:1156085807.163658.255070@i3g2000cwc.googlegroups.com...
>>> How do you get a pointer to an empty sequence? Unless you are talking of
>>> iterators in the sense of the STL...
>>>
>> yes, that is exactly what I'm referring to. An iterator can be
>> implemented as a pointer, with the end() iterator being "one past the
>> end". In the case of an empty sequence, you may well use a NULL pointer
>> to store the result of both begin() and end().
>
> But the wording of 5.7/3 seems to imply that the end() iterator cannot be a
> NULL pointer.

If end() were not allowed to return a NULL pointer, that would render
this partial vector implementation non-conforming:

template<typename T, Alloc>
class vector
{
  T *m_start, *m_end, *m_storage_end;
  //...
public:
  vector() : m_start(0), m_end(0), m_storage_end(0) {}
  //...
  T *begin() { return m_start; }
  T *end { return m_end }
  //...
};

It would also seem to require that and such implementation allocate
memory even when default constructed just to allow begin() and end() to
return (the same) non-NULL pointer.



--
Clark S. Cox III
clarkcox3@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Mon, 21 Aug 2006 16:12:34 CST
Raw View
"Matthias Hofmann" wrote:

> But the wording of 5.7/3 seems to imply that the end() iterator cannot be a
> NULL pointer.

I don't see how.  5.7/6 (which is, I think, the passage you mean) only
applies to pointers into arrays.  There's no guarantee or requirement
that vector::iterators behave in the same way, even if the iterators
happen to be implemented as pointers.  In particular, there is no
requirement that end() return a pointer to one-past-the-end of an
array.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Mon, 21 Aug 2006 22:48:19 CST
Raw View
"Matthias Hofmann" wrote:
> "Earl Purple" <earlpurple@gmail.com> schrieb im Newsbeitrag
> news:1156085807.163658.255070@i3g2000cwc.googlegroups.com...
.
> > yes, that is exactly what I'm referring to. An iterator can be
> > implemented as a pointer, with the end() iterator being "one past the
> > end". In the case of an empty sequence, you may well use a NULL pointer
> > to store the result of both begin() and end().
>
> But the wording of 5.7/3 seems to imply that the end() iterator cannot be a
> NULL pointer.

Are you sure you're citing the right section? I don't see a connection
between 5.7/3 and this subject; it's just defines the operators + and -
as returning the sum and difference, respectively, of their operands.
That's meaningful for arithmetic types, but useless for pointer types,
where "sum" and "difference" have no intrinsic meaning; but either way,
it doesn't seem relevant to end() and NULL.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 17 Aug 2006 17:34:15 GMT
Raw View
 posted:

> Frederick Gotham wrote:
>> SuperKoko posted:
>>
>>
>> >>     (1) A pointer to one past the last element of an array shall not
>> >>     be a
>> >> null pointer.
>> >>
>> >> or:
>> >>
>> >>     (2) This Standard imposes no restriction whereby a pointer to
>> >>     one past
>> >> the last element of an array shall not be a null pointer.
>> >>
>> >> Something like that.
>> >>
>> > Or, a third possibility:
>> > (3) It is implementation-defined whether a pointer to one past the
>> > last element of an array can be a null pointer.
>>
>>
>> That's exactly the same as number (2), because it permits an
>> implementation to have a "one past last" pointer which is null.
>
> Not true. If it's implementation-defined, an implmentation is required
> to document whether or not it has chosen to allow this possibility.
> Option 2 imposes no such requirement.


Nonetheless, it allows the possiblity, and so we must take this into
account when writing portable code. The following function is broken if a
pointer to "one past last" can be null:

void ProcessArray(char unsigned const *p1, char unsigned const *p2)
{
    if (!p) return ProcessNullTerminatedArray(p1);

    do
    {
        *p++ *= 5;
    } while(p1 != p2);
}

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Matthias Hofmann" <hofmann@anvil-soft.com>
Date: Thu, 17 Aug 2006 13:39:02 CST
Raw View
"James Kanze" <kanze.james@neuf.fr> schrieb im Newsbeitrag
news:ebt39f$9o5$1@emma.aioe.org...
Frederick Gotham wrote:
> > Matthias Hofmann posted:
> >>> On the contrary, it would make it yield perfectly defined
> >>> behaviour.  (Perhaps you read it wrong?)

>>> What I wanted to say is that in your example, there cannot be
>>> an overflow, so a pointer to "one past last" cannot result in
>>> a null pointer.

>> If we have 32-Bit pointers, and if the address of the last
>> element in the array is 0xFFFFFFFF, then the address of "one
>> past last" would be 0.

> I'm not sure.  It depends on how you define "overflow" in this
> context.  Pointers are not int's, and while I know what
> "overflow" means for an int, it's less clear what it means for a
> pointer.

> On the other hand, a machine with 32 bit pointers could very
> well use the bit pattern 0xFFFFFFFF for null pointers, and
> allocate a one byte array at the address 0xFFFFFFFE.  Basically,
> I agree with your point: unless the standard explicitly says
> that a pointer one past the end cannot be a null pointer, it
> might be.  Whether the standard actually gives this guarantee or
> not is IMHO an open question.

Another open question is whether the following code works as intended:

char arr[] = "Hello";
char* p = arr + sizeof arr;
ptrdiff_t size = p - arr;

Note that section 5.7/6 gives no such guarantee: "When two pointers to
elements of the same array object are subtracted, the result is the
difference of the subscripts of the two array elements." However, 'p' in my
example does not point to an element of the array.

5.7/6 also describes what happens when a pointer to "one past the last" is
involved: "Moreover, if the expression P points either to an element of an
array object or one past the last element of an array object, and the
expression Q points to the last element of the same array object, the
expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and
as -((P)-((Q)+1)), and has the value zero if the expression P points one
past the last element of the array object, even though the expression (Q)+1
does not point to an element of the array object." Unfortunately, it does
*not* say that the result is the difference of the subscripts. Actually, the
information given here is rather useless, as it only says that the result
will be zero if both pointers point to one past the last element.

So what does that mean? I have always thought that a pointer to "one past
last" can be used to determine the entire size of an array?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Fri, 18 Aug 2006 09:59:38 CST
Raw View
Frederick Gotham wrote:
> James Kuyper wrote:
> > Frederick Gotham wrote:
> >> SuperKoko posted:
> >> >>     (1) A pointer to one past the last element of an array shall not
> >> >>     be a
> >> >> null pointer.
> >> >>
> >> >> or:
> >> >>
> >> >>     (2) This Standard imposes no restriction whereby a pointer to
> >> >>     one past
> >> >> the last element of an array shall not be a null pointer.
> >> >>
> >> >> Something like that.
> >> >>
> >> > Or, a third possibility:
> >> > (3) It is implementation-defined whether a pointer to one past the
> >> > last element of an array can be a null pointer.
> >> That's exactly the same as number (2), because it permits an
> >> implementation to have a "one past last" pointer which is null.
> >
> > Not true. If it's implementation-defined, an implmentation is required
> > to document whether or not it has chosen to allow this possibility.
> > Option 2 imposes no such requirement.
>
> Nonetheless, it allows the possiblity, and so we must take this into
> account when writing portable code.

Of couse: the difference between implementation-defined and unspecified
matters only for non-portable code. Not all code needs to be portable.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Earl Purple" <earlpurple@gmail.com>
Date: Fri, 18 Aug 2006 10:28:25 CST
Raw View
"Heinz Ozwirk" wrote:
>
> A pointer to one past the last element cannot be 0. The standard already
> says that (5.7/3) "if the expression Q points one past the last element of
> an array object, the expression (Q) - 1 points to the last element of the
> array object". That would be impossible if all one past the end pointers
> would be null pointers. But it wouldn't harm to explicitly state that a one
> past the end pointer cannot be a null pointer.

Suppose I implement an empty sequence with a null pointer. Then my
"one-past-the-end" will also be NULL because it will be the same as my
original pointer.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Fri, 18 Aug 2006 11:09:27 CST
Raw View
Matthias Hofmann wrote:
> "James Kanze" <kanze.james@neuf.fr> schrieb im Newsbeitrag
> news:ebt39f$9o5$1@emma.aioe.org...

> > On the other hand, a machine with 32 bit pointers could very
> > well use the bit pattern 0xFFFFFFFF for null pointers, and
> > allocate a one byte array at the address 0xFFFFFFFE.
> > Basically, I agree with your point: unless the standard
> > explicitly says that a pointer one past the end cannot be a
> > null pointer, it might be.  Whether the standard actually
> > gives this guarantee or not is IMHO an open question.

> Another open question is whether the following code works as
> intended:

> char arr[] = "Hello";
> char* p = arr + sizeof arr;
> ptrdiff_t size = p - arr;

> Note that section 5.7/6 gives no such guarantee: "When two
> pointers to elements of the same array object are subtracted,
> the result is the difference of the subscripts of the two
> array elements." However, 'p' in my example does not point to
> an element of the array.

> 5.7/6 also describes what happens when a pointer to "one past
> the last" is involved: "Moreover, if the expression P points
> either to an element of an array object or one past the last
> element of an array object, and the expression Q points to the
> last element of the same array object, the expression
> ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as
> -((P)-((Q)+1)), and has the value zero if the expression P
> points one past the last element of the array object, even
> though the expression (Q)+1 does not point to an element of
> the array object." Unfortunately, it does *not* say that the
> result is the difference of the subscripts. Actually, the
> information given here is rather useless, as it only says that
> the result will be zero if both pointers point to one past the
> last element.

> So what does that mean? I have always thought that a pointer
> to "one past last" can be used to determine the entire size of
> an array?

I'm pretty sure that this is the intent.  Frederick has already
proposed clear and simple wording with regards to a one past the
end pointer being null---IMHO, the intent was that it not be
null, but as long as the standard doesn't say so clearly,
there's no such requirement.  Here, I think something along the
lines of saying that for the purposes of address arithmetic, one
past the end of the array acts as if it were part of the array.

If we look further, I suspect that there might be other cases
where the standard speaks of guarantees concerning pointers to
objects, and it really means pointers to objects and pointers
one past the end of an array.

Historically, I've always thought that the solution involved a
grill, with four mutually exclusive categories: invalid
pointers, null pointers, pointers to an object, and pointers one
past the end.  The idea being that for anything concerning
pointers, you create an n dimensional array (with n the number
of pointers involved), and specify each and every element of the
array.  (Actually, you only need three categories.  An element
with "invalid pointer" as one of the indexes is always undefined
behavior.)  But it's even more complicated than that, because
for some operations involving two pointers, the behavior depends
on whether the two pointers point into the same object or not
(and in such cases, a pointer one past the end generally behaves
as if it points into the object).

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Fri, 18 Aug 2006 16:51:20 GMT
Raw View
Kuyper posted:

> Of couse: the difference between implementation-defined and unspecified
> matters only for non-portable code. Not all code needs to be portable.


Yes, but here on comp.std.c++, and similarly on comp.lang.c++, and on
comp.lang.c++.moderated, we discuss portable code.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Fri, 18 Aug 2006 12:38:57 CST
Raw View
Frederick Gotham wrote:
> Kuyper posted:
>
> > Of couse: the difference between implementation-defined and unspecified
> > matters only for non-portable code. Not all code needs to be portable.
>
>
> Yes, but here on comp.std.c++, and similarly on comp.lang.c++, and on
> comp.lang.c++.moderated, we discuss portable code.

I'm reading this in comp.std.c++; I'm not sure what the rules are in
comp.lang.c++.moderated. In comp.std.c++, we discuss the C++ standard,
which does cover portable code, but it also covers non-portable code,
at least when the reasons why the code is non-portable is because the
behavior, according to the C++ standard, is unspecified (which includes
implementation-defined behavior). We also discuss code for which the
C++ standard mandates a diagnostic. Even code whose behavior is
undefined is on-topic here, insofar as it's a question about whether or
not the C++ standard says that the behavior is undefined.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sat, 19 Aug 2006 09:55:54 CST
Raw View
Frederick Gotham wrote:
> Kuyper posted:
>
> > Of couse: the difference between implementation-defined and unspecified
> > matters only for non-portable code. Not all code needs to be portable.
>
>
> Yes, but here on comp.std.c++, and similarly on comp.lang.c++, and on
> comp.lang.c++.moderated, we discuss portable code.

Actually, I believe that discussions of "portable C++ code" would be
more on-topic in alt.oxymoron. :-) After all, C++ (by way of its C
roots) actively stymies writing portable programs - and it does so by
design. C++ sacrifices source code portabillity in a tradeoff with
language portability. A C++ program may not be very portable, but C++
the language is.

And given the computing landscape of the 70s in which C grew up - this
calculation makes perfect sense: the prospect of running one program on
even more than a single machine (much less, two different kinds of
machines) no doubt seemed to have far less practical value than the
prospect of using a single computer language to write programs on
different types of computers.

Today, that 70s era calculation of language portability versus source
code portability would probably turn out differently. Today's computers
present a much more homogenized development environment than the
machines of the 70s. Computers have also greatly increased in their
number and affordability. So today there is much more value in being
able to write one program and be able to run it on different types of
hardware than there is value in being able to write a unique program
for each and every type of architecture - and be able to do write each
one in C++.

So the word "portable" when describing C++ really refers to the
language's portability - and not to the portability of its source code.
Consequently, if the ability to program in C++ across a diverse set of
computing hardware is one's definition of "portable" than, yes, C++ is
portable. If  on the other hand, the portability of a computer language
is measured in terms of how easily and reliabily a single program can
made to run on a diverse set of computer hardware, then "portable C++
code" would be an oxymoron.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Sat, 19 Aug 2006 15:02:20 GMT
Raw View
"Earl Purple" <earlpurple@gmail.com> schrieb im Newsbeitrag
news:1155903520.290969.259430@75g2000cwc.googlegroups.com...
>
> "Heinz Ozwirk" wrote:
>>
>> A pointer to one past the last element cannot be 0. The standard already
>> says that (5.7/3) "if the expression Q points one past the last element
>> of
>> an array object, the expression (Q) - 1 points to the last element of the
>> array object". That would be impossible if all one past the end pointers
>> would be null pointers. But it wouldn't harm to explicitly state that a
>> one
>> past the end pointer cannot be a null pointer.
>
> Suppose I implement an empty sequence with a null pointer. Then my
> "one-past-the-end" will also be NULL because it will be the same as my
> original pointer.

How do you get a pointer to an empty sequence? Unless you are talking of
iterators in the sense of the STL...

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Sat, 19 Aug 2006 15:03:04 GMT
Raw View
"kanze" <kanze@gabi-soft.fr> schrieb im Newsbeitrag
news:1155910235.031932.26010@i42g2000cwa.googlegroups.com...

> I'm pretty sure that this is the intent.  Frederick has already
> proposed clear and simple wording with regards to a one past the
> end pointer being null---IMHO, the intent was that it not be
> null, but as long as the standard doesn't say so clearly,
> there's no such requirement.  Here, I think something along the
> lines of saying that for the purposes of address arithmetic, one
> past the end of the array acts as if it were part of the array.
>
> If we look further, I suspect that there might be other cases
> where the standard speaks of guarantees concerning pointers to
> objects, and it really means pointers to objects and pointers
> one past the end of an array.

I remember that there once was a discussion about whether the following is
undefined behaviour:

char arr[] = "Hello";
int i = sizeof arr / sizeof arr[0];
char* p = &arr[i];

The point is that in the last line, a pointer one past the end of the array
is dereferenced in order to take the address of the 'object' it points to.
If I remember correctly, there is an exception in the C standard that makes
this legal, while it is undefined behaviour in C++.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sat, 19 Aug 2006 22:51:13 GMT
Raw View
Greg Herlihy posted:

> A C++ program may not be very portable, but C++ the language is.


Ridiculous! It's quite easy to keep one's code, and thus one's program,
portable.


> And given the computing landscape of the 70s in which C grew up - this
> calculation makes perfect sense: the prospect of running one program on
> even more than a single machine (much less, two different kinds of
> machines) no doubt seemed to have far less practical value than the
> prospect of using a single computer language to write programs on
> different types of computers.


All my code is fully portable. All of it.


> So the word "portable" when describing C++ really refers to the
> language's portability - and not to the portability of its source code.
> Consequently, if the ability to program in C++ across a diverse set of
> computing hardware is one's definition of "portable" than, yes, C++ is
> portable. If  on the other hand, the portability of a computer language
> is measured in terms of how easily and reliabily a single program can
> made to run on a diverse set of computer hardware, then "portable C++
> code" would be an oxymoron.


No, not all. I am aware of the restrictions and freedoms which an
implementation of C++ may have. With this knowledge, I can write fully-
portable, Standard-compliant code.


--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sat, 19 Aug 2006 22:50:38 GMT
Raw View
"Matthias Hofmann" posted:

> I remember that there once was a discussion about whether the following
> is undefined behaviour:
>
> char arr[] = "Hello";
> int i = sizeof arr / sizeof arr[0];
> char* p = &arr[i];
>
> The point is that in the last line, a pointer one past the end of the
> array is dereferenced in order to take the address of the 'object' it
> points to. If I remember correctly, there is an exception in the C
> standard that makes this legal, while it is undefined behaviour in C++.


Indeed, which is why we must write:

    char *p = arr + i;

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Sun, 20 Aug 2006 12:36:10 CST
Raw View
"Matthias Hofmann" wrote:
> char arr[] = "Hello";
> int i = sizeof arr / sizeof arr[0];
> char* p = &arr[i];
>
> The point is that in the last line, a pointer one past the end of the array
> is dereferenced in order to take the address of the 'object' it points to.
> If I remember correctly, there is an exception in the C standard that makes
> this legal, while it is undefined behaviour in C++.
>
No. Applying the unary * operator doesn't create UB (you can read the
expr.unary.op)
However an lvalue-to-rvalue conversion done on such lvalue or an
assignment of such lvalue has UB.

Unfortunately, the term "dereferencing the null pointer" is currently
abusively used in the ISO standard as being UB.
There is an active issue about that.
http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#232

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kst-u@mib.org (Keith Thompson)
Date: Sun, 20 Aug 2006 17:49:54 GMT
Raw View
"kanze" <kanze@gabi-soft.fr> writes:
[...]
> Historically, I've always thought that the solution involved a
> grill, with four mutually exclusive categories: invalid
> pointers, null pointers, pointers to an object, and pointers one
> past the end.
[...]

Except that a pointer just past the end of an object can also be a
pointer to another object, if the two objects happen to be adjacent in
memory.  (Obviously in that case the just-past-the-end pointer cannot
be null.)

I know that the C99 standard specifically mentions this.  I don't know
whether the C++ standard does, but I presume it doesn't prohibit it;
if it did, objects couldn't be allocated adjacent to each other.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Earl Purple" <earlpurple@gmail.com>
Date: Sun, 20 Aug 2006 14:15:53 CST
Raw View
> How do you get a pointer to an empty sequence? Unless you are talking of
> iterators in the sense of the STL...
>
yes, that is exactly what I'm referring to. An iterator can be
implemented as a pointer, with the end() iterator being "one past the
end". In the case of an empty sequence, you may well use a NULL pointer
to store the result of both begin() and end().

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Matthias Hofmann" <hofmann@anvil-soft.com>
Date: Mon, 21 Aug 2006 02:46:51 CST
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:zTGFg.12857$j7.325293@news.indigo.ie...

>> So the word "portable" when describing C++ really refers to the
>> language's portability - and not to the portability of its source code.
>> Consequently, if the ability to program in C++ across a diverse set of
>> computing hardware is one's definition of "portable" than, yes, C++ is
>> portable. If  on the other hand, the portability of a computer language
>> is measured in terms of how easily and reliabily a single program can
>> made to run on a diverse set of computer hardware, then "portable C++
>> code" would be an oxymoron.
>
>
> No, not all. I am aware of the restrictions and freedoms which an
> implementation of C++ may have. With this knowledge, I can write fully-
> portable, Standard-compliant code.

Source code portability usually ends as soon as you are calling a function
from the Windows API. Or XWindows, Gnome, KDE, MFC, DirectX... In C++, its
easy to write portable code, but hard to write portable programs.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Matthias Hofmann" <hofmann@anvil-soft.com>
Date: Mon, 21 Aug 2006 02:46:56 CST
Raw View
"SuperKoko" <tabkannaz@yahoo.fr> schrieb im Newsbeitrag
news:1156071550.941088.290450@m73g2000cwd.googlegroups.com...
>
> "Matthias Hofmann" wrote:
>> char arr[] = "Hello";
>> int i = sizeof arr / sizeof arr[0];
>> char* p = &arr[i];
>>
>> The point is that in the last line, a pointer one past the end of the
>> array
>> is dereferenced in order to take the address of the 'object' it points
>> to.
>> If I remember correctly, there is an exception in the C standard that
>> makes
>> this legal, while it is undefined behaviour in C++.
>>
> No. Applying the unary * operator doesn't create UB (you can read the
> expr.unary.op)
> However an lvalue-to-rvalue conversion done on such lvalue or an
> assignment of such lvalue has UB.

So it is not undefined behaviour to code like this?

char a[10];
char* p = &a[10]

> Unfortunately, the term "dereferencing the null pointer" is currently
> abusively used in the ISO standard as being UB.
> There is an active issue about that.
> http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#232

This sounds like the standard says it is not undefined behaviour, but there
is ongoing discussion about whether this should be changed?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Mon, 21 Aug 2006 09:40:16 GMT
Raw View
"James Kanze" <kanze.james@neuf.fr> schrieb im Newsbeitrag
news:ebt39f$9o5$1@emma.aioe.org...
Frederick Gotham wrote:
> > Matthias Hofmann posted:
> >>> On the contrary, it would make it yield perfectly defined
> >>> behaviour.  (Perhaps you read it wrong?)

>>> What I wanted to say is that in your example, there cannot be
>>> an overflow, so a pointer to "one past last" cannot result in
>>> a null pointer.

>> If we have 32-Bit pointers, and if the address of the last
>> element in the array is 0xFFFFFFFF, then the address of "one
>> past last" would be 0.

> I'm not sure.  It depends on how you define "overflow" in this
> context.  Pointers are not int's, and while I know what
> "overflow" means for an int, it's less clear what it means for a
> pointer.

> On the other hand, a machine with 32 bit pointers could very
> well use the bit pattern 0xFFFFFFFF for null pointers, and
> allocate a one byte array at the address 0xFFFFFFFE.  Basically,
> I agree with your point: unless the standard explicitly says
> that a pointer one past the end cannot be a null pointer, it
> might be.  Whether the standard actually gives this guarantee or
> not is IMHO an open question.

Another open question is whether the following code works as intended:

char arr[] = "Hello";
char* p = arr + sizeof arr;
ptrdiff_t size = p - arr;

Note that section 5.7/6 gives no such guarantee: "When two pointers to
elements of the same array object are subtracted, the result is the
difference of the subscripts of the two array elements." However, 'p' in my
example does not point to an element of the array.

5.7/6 also describes what happens when a pointer to "one past the last" is
involved: "Moreover, if the expression P points either to an element of an
array object or one past the last element of an array object, and the
expression Q points to the last element of the same array object, the
expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and
as -((P)-((Q)+1)), and has the value zero if the expression P points one
past the last element of the array object, even though the expression (Q)+1
does not point to an element of the array object." Unfortunately, it does
*not* say that the result is the difference of the subscripts. Actually, the
information given here is rather useless, as it only says that the result
will be zero if both pointers point to one past the last element.

So what does that mean? I have always thought that a pointer to "one past
last" can be used to determine the entire size of an array?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Mon, 21 Aug 2006 10:03:05 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:rL1Fg.12782$j7.325006@news.indigo.ie...

> Nonetheless, it allows the possiblity, and so we must take this into
> account when writing portable code. The following function is broken if a
> pointer to "one past last" can be null:
>
> void ProcessArray(char unsigned const *p1, char unsigned const *p2)
> {
>    if (!p) return ProcessNullTerminatedArray(p1);
>
>    do
>    {
>        *p++ *= 5;
>    } while(p1 != p2);
> }

Your code does not compile - where does 'p' come from?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Tue, 15 Aug 2006 17:07:29 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:6_GCg.12494$j7.321517@news.indigo.ie...
> Matthias Hofmann posted:
>
>>> On the contrary, it would make it yield perfectly defined behaviour.
>> (Perhaps
>>> you read it wrong?)
>>
>> What I wanted to say is that in your example, there cannot be an
>> overflow, so a pointer to "one past last" cannot result in a null
>> pointer.
>
>
> If we have 32-Bit pointers, and if the address of the last element in the
> array is 0xFFFFFFFF, then the address of "one past last" would be 0.

Yes, but this would be an overflow, and the passage I quoted says that this
is not supposed to happen: "If both the pointer operand and the result point
to elements of the same array object, or one past the last element of the
array object, the evaluation shall not produce an overflow".

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 15 Aug 2006 18:51:11 GMT
Raw View
"Matthias Hofmann" posted:

>> If we have 32-Bit pointers, and if the address of the last element in
>> the array is 0xFFFFFFFF, then the address of "one past last" would be
>> 0.
>
> Yes, but this would be an overflow, and the passage I quoted says that
> this is not supposed to happen: "If both the pointer operand and the
> result point to elements of the same array object, or one past the last
> element of the array object, the evaluation shall not produce an
> overflow".


I think that depends on one's definition of "overflow". The following doesn't
overflow:

    unsigned i = UINT_MAX;
    ++i;

I think the Standard even uses such language as "unsigned integer arithmetic
does not overflow, as the result is reduced modulo...".

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Wed, 16 Aug 2006 14:44:53 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:4UnEg.12708$j7.324778@news.indigo.ie...
> "Matthias Hofmann" posted:
>
>>> If we have 32-Bit pointers, and if the address of the last element in
>>> the array is 0xFFFFFFFF, then the address of "one past last" would be
>>> 0.
>>
>> Yes, but this would be an overflow, and the passage I quoted says that
>> this is not supposed to happen: "If both the pointer operand and the
>> result point to elements of the same array object, or one past the last
>> element of the array object, the evaluation shall not produce an
>> overflow".
>
>
> I think that depends on one's definition of "overflow". The following
> doesn't
> overflow:
>
>    unsigned i = UINT_MAX;
>    ++i;
>
> I think the Standard even uses such language as "unsigned integer
> arithmetic
> does not overflow, as the result is reduced modulo...".

Section 3.9.1/4 has a footnote 41) that indeed uses such language. But then,
what is an overflow in the sense of 6.5.6/8? Is there a definition for
'overflow' in the standard?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Wed, 16 Aug 2006 09:44:49 CST
Raw View
"Matthias Hofmann" wrote:
> "Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
> news:6_GCg.12494$j7.321517@news.indigo.ie...
> > Matthias Hofmann posted:
> >
> >>> On the contrary, it would make it yield perfectly defined behaviour.
> >> (Perhaps
> >>> you read it wrong?)
> >>
> >> What I wanted to say is that in your example, there cannot be an
> >> overflow, so a pointer to "one past last" cannot result in a null
> >> pointer.
> >
> >
> > If we have 32-Bit pointers, and if the address of the last element in the
> > array is 0xFFFFFFFF, then the address of "one past last" would be 0.
>
> Yes, but this would be an overflow, and the passage I quoted says that this
> is not supposed to happen: "If both the pointer operand and the result point
> to elements of the same array object, or one past the last element of the
> array object, the evaluation shall not produce an overflow".
>
Matthias, you're perfectly right.
In addition, the standard doesn't specify what are the representations
of null pointers.
0xFFFFFFF is a possible value (for a 32 bit pointer type whose)
0x80000000 is another possibility.
0x4547 is yet another possibility!

"no overflow" just means that it doesn't crash nor throw any exception
(as a bound-checked implementation might do if it was not aware of the
standard).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hofmann@anvil-soft.com ("Matthias Hofmann")
Date: Wed, 16 Aug 2006 16:22:14 GMT
Raw View
"SuperKoko" <tabkannaz@yahoo.fr> schrieb im Newsbeitrag
news:1155208561.465733.256330@m79g2000cwm.googlegroups.com...

>>     (1) A pointer to one past the last element of an array shall not be a
>> null pointer.
>>
>> or:
>>
>>     (2) This Standard imposes no restriction whereby a pointer to one
>> past
>> the last element of an array shall not be a null pointer.
>>
>> Something like that.
>>
> Or, a third possibility:
> (3) It is implementation-defined whether a pointer to one past the last
> element of an array can be a null pointer.

Wouldn't your third possibility make it rather hard to write portable code
for trivial tasks?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kanze.james@neuf.fr (James Kanze)
Date: Wed, 16 Aug 2006 16:24:33 GMT
Raw View
Frederick Gotham wrote:
 > Matthias Hofmann posted:
 >>> On the contrary, it would make it yield perfectly defined
 >>> behaviour.  (Perhaps you read it wrong?)

 >> What I wanted to say is that in your example, there cannot be
 >> an overflow, so a pointer to "one past last" cannot result in
 >> a null pointer.

 > If we have 32-Bit pointers, and if the address of the last
 > element in the array is 0xFFFFFFFF, then the address of "one
 > past last" would be 0.

I'm not sure.  It depends on how you define "overflow" in this
context.  Pointers are not int's, and while I know what
"overflow" means for an int, it's less clear what it means for a
pointer.

On the other hand, a machine with 32 bit pointers could very
well use the bit pattern 0xFFFFFFFF for null pointers, and
allocate a one byte array at the address 0xFFFFFFFE.  Basically,
I agree with your point: unless the standard explicitly says
that a pointer one past the end cannot be a null pointer, it
might be.  Whether the standard actually gives this guarantee or
not is IMHO an open question.  A very strict interpretation of
the wording in the C++98 standard says that is it cannot be.
On the other hand, a strict interpretation of the C90 standard
allows it, and I've fairly certain that the intent here was to
be compatible.  Frankly, I suspect that you've touched on a
point no one actually considered, and that the difference here
is more or less accidental.  (I also think that the intent in C
was that a pointer one past the end cannot be null, and that
this possibility simply didn't occur to anyone at the time.  But
that's more or less a feeling, and not based on any concrete
evidence.)

--=20
James Kanze                                    kanze.james@neuf.fr
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Wed, 16 Aug 2006 12:28:53 CST
Raw View
"Matthias Hofmann" wrote:
> "SuperKoko" <tabkannaz@yahoo.fr> schrieb im Newsbeitrag
> news:1155208561.465733.256330@m79g2000cwm.googlegroups.com...
>
> >>     (1) A pointer to one past the last element of an array shall not be a
> >> null pointer.
> >>
> >> or:
> >>
> >>     (2) This Standard imposes no restriction whereby a pointer to one
> >> past
> >> the last element of an array shall not be a null pointer.
> >>
> >> Something like that.
> >>
> > Or, a third possibility:
> > (3) It is implementation-defined whether a pointer to one past the last
> > element of an array can be a null pointer.
>
> Wouldn't your third possibility make it rather hard to write portable code
> for trivial tasks?

I don't think so. It could certainly cause problems for some code, but
not for most code.

Just about the only thing you can do with a one-past-the-end pointer is
compare it with other pointers. Comparison for equality with non-null
pointers would give precisely the right result. A one-past-the-end
pointer can only be compared for order, with meaningful results, to
other pointers into the same array, and it's supposed to always compare
greater than any of them. The result of comparing null pointers for
order is unspecified, so an implementor is free to  define that any
null pointer compares greater than any non-null pointer (which is not,
admittedly, the natural result on many implementations). If that is
done, I don't see any problem with a one-past-the-end pointer being
null unless the code directly compares the one-past-the-end pointer for
equality with a null pointer. I'm sure that there's a lot of code out
there which does precisely that, which is why I'm opposed to this
resolution to the issue. However,  I don't think such code is the norm.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 17 Aug 2006 16:29:13 GMT
Raw View
SuperKoko posted:


>>     (1) A pointer to one past the last element of an array shall not be
>>     a
>> null pointer.
>>
>> or:
>>
>>     (2) This Standard imposes no restriction whereby a pointer to one
>>     past
>> the last element of an array shall not be a null pointer.
>>
>> Something like that.
>>
> Or, a third possibility:
> (3) It is implementation-defined whether a pointer to one past the last
> element of an array can be a null pointer.


That's exactly the same as number (2), because it permits an implementation
to have a "one past last" pointer which is null.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 17 Aug 2006 16:29:42 GMT
Raw View
James Kanze posted:

> Basically, I agree with your point: unless the standard explicitly says
> that a pointer one past the end cannot be a null pointer, it might be.


Someone sees where I'm coming from, lovely.


> Whether the standard actually gives this guarantee or not is IMHO an
> open question. A very strict interpretation of the wording in the C++98
> standard says that is it cannot be. On the other hand, a strict
> interpretation of the C90 standard allows it, and I've fairly certain
> that the intent here was to be compatible.  Frankly, I suspect that
> you've touched on a point no one actually considered, and that the
> difference here is more or less accidental.  (I also think that the
> intent in C was that a pointer one past the end cannot be null, and that
> this possibility simply didn't occur to anyone at the time.  But that's
> more or less a feeling, and not based on any concrete evidence.)


To rectify the entire situation, the Standard should specify clearly and
precisely:

    (1) A pointer to one past the last shall not be null
or
    (2) A pointer to one past the last is permitted to be null

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Thu, 17 Aug 2006 12:07:53 CST
Raw View
Frederick Gotham wrote:
> SuperKoko posted:
>
>
> >>     (1) A pointer to one past the last element of an array shall not be
> >>     a
> >> null pointer.
> >>
> >> or:
> >>
> >>     (2) This Standard imposes no restriction whereby a pointer to one
> >>     past
> >> the last element of an array shall not be a null pointer.
> >>
> >> Something like that.
> >>
> > Or, a third possibility:
> > (3) It is implementation-defined whether a pointer to one past the last
> > element of an array can be a null pointer.
>
>
> That's exactly the same as number (2), because it permits an implementation
> to have a "one past last" pointer which is null.

Not true. If it's implementation-defined, an implmentation is required
to document whether or not it has chosen to allow this possibility.
Option 2 imposes no such requirement.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sat, 5 Aug 2006 14:56:55 GMT
Raw View
May I propose, in the next Standard, that it be explicitly stated whether a
pointer to "one past the last element of an array" can be a null pointer.

There's been quite a bit of controversy about this in the past, and no solid
answer has ever been given. So maybe it would be better if the Standard
spelled it out in black-and-white. Either:

    (1) A pointer to one past the last element of an array shall not be a
null pointer.

or:

    (2) This Standard imposes no restriction whereby a pointer to one past
the last element of an array shall not be a null pointer.

Something like that.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: hozwirk.SPAM@arcor.de ("Heinz Ozwirk")
Date: Tue, 8 Aug 2006 12:06:09 GMT
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:Z11Bg.12280$j7.321393@news.indigo.ie...
> May I propose, in the next Standard, that it be explicitly stated whether
> a
> pointer to "one past the last element of an array" can be a null pointer.
>
> There's been quite a bit of controversy about this in the past, and no
> solid
> answer has ever been given. So maybe it would be better if the Standard
> spelled it out in black-and-white. Either:
>
>    (1) A pointer to one past the last element of an array shall not be a
> null pointer.
>
> or:
>
>    (2) This Standard imposes no restriction whereby a pointer to one past
> the last element of an array shall not be a null pointer.
>
> Something like that.

A pointer to one past the last element cannot be 0. The standard already
says that (5.7/3) "if the expression Q points one past the last element of
an array object, the expression (Q) - 1 points to the last element of the
array object". That would be impossible if all one past the end pointers
would be null pointers. But it wouldn't harm to explicitly state that a one
past the end pointer cannot be a null pointer.

    Heinz

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: clarkcox3@gmail.com ("Clark S. Cox III")
Date: Tue, 8 Aug 2006 15:39:14 GMT
Raw View
On 2006-08-08 08:06:09 -0400, hozwirk.SPAM@arcor.de ("Heinz Ozwirk") said:

> "Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
> news:Z11Bg.12280$j7.321393@news.indigo.ie...
>> May I propose, in the next Standard, that it be explicitly stated whether a
>> pointer to "one past the last element of an array" can be a null pointer.
>>
>> There's been quite a bit of controversy about this in the past, and no solid
>> answer has ever been given. So maybe it would be better if the Standard
>> spelled it out in black-and-white. Either:
>>
>>    (1) A pointer to one past the last element of an array shall not be a
>> null pointer.
>>
>> or:
>>
>>    (2) This Standard imposes no restriction whereby a pointer to one past
>> the last element of an array shall not be a null pointer.
>>
>> Something like that.
>
> A pointer to one past the last element cannot be 0. The standard
> already says that (5.7/3) "if the expression Q points one past the last
> element of an array object, the expression (Q) - 1 points to the last
> element of the array object". That would be impossible if all one past
> the end pointers would be null pointers.

While that does prevent having *all* one-past-the-end pointers be null
pointers, it doesn't prevent any individual one-past-the-end pointer
from being a NULL pointer.


> But it wouldn't harm to explicitly state that a one past the end
> pointer cannot be a null pointer.


--
Clark S. Cox, III
clarkcox3@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 8 Aug 2006 16:32:36 GMT
Raw View
"Heinz Ozwirk" posted:

> A pointer to one past the last element cannot be 0. The standard already
> says that (5.7/3) "if the expression Q points one past the last element
> of an array object, the expression (Q) - 1 points to the last element of
> the array object". That would be impossible if all one past the end
> pointers would be null pointers.


No, not impossible. Let's say we have a 16-Bit unsigned integer (with no
padding). It has 65536 unique values, and can store values in the range 0
through 65535.

If 65535 were to represent the last available byte, then 65535 + 1 would
represent the "one past last" byte. Obeying modulo arithmetic for unsigned
types, 65535 + 1 = 0. So zero could represent the "one past last" pointer.

If we subtract 1 from 0, we're left with 65535.

It would be possible to have a system where a pointer to "one past last" is
null, and still satisfy the following:

    char *p = &last_element + 1;

    char *p_last_element = p - 1;

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Tue, 8 Aug 2006 11:34:28 CST
Raw View
"Heinz Ozwirk" wrote:
.
> A pointer to one past the last element cannot be 0. The standard already
> says that (5.7/3) "if the expression Q points one past the last element of
> an array object, the expression (Q) - 1 points to the last element of the
> array object". That would be impossible if all one past the end pointers
> would be null pointers.

Why would that be impossible?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Wed, 9 Aug 2006 06:35:56 CST
Raw View
Frederick Gotham wrote:

> No, not impossible. Let's say we have a 16-Bit unsigned integer (with no
> padding). It has 65536 unique values, and can store values in the range 0
> through 65535.
>
> If 65535 were to represent the last available byte, then 65535 + 1 would
> represent the "one past last" byte. Obeying modulo arithmetic for unsigned
> types, 65535 + 1 = 0. So zero could represent the "one past last" pointer.

But how would this hypothetical implementation comply with 4.10/1,
which says that the null pointer value (the result of converting the
null pointer constant to a pointer type) is distinguishable from every
other value of pointer type?

I would think that the purpose of this requirement is to outlaw any
implementation in which valid pointer arithmetic can produce a result
that "collides" with the null pointer value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Eisenbart" <hofmann@anvil-soft.com>
Date: Wed, 9 Aug 2006 09:28:48 CST
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:dt%Bg.12374$j7.321432@news.indigo.ie...
> "Heinz Ozwirk" posted:
>
> > A pointer to one past the last element cannot be 0. The standard already
> > says that (5.7/3) "if the expression Q points one past the last element
> > of an array object, the expression (Q) - 1 points to the last element of
> > the array object". That would be impossible if all one past the end
> > pointers would be null pointers.
>
>
> No, not impossible. Let's say we have a 16-Bit unsigned integer (with no
> padding). It has 65536 unique values, and can store values in the range 0
> through 65535.
>
> If 65535 were to represent the last available byte, then 65535 + 1 would
> represent the "one past last" byte. Obeying modulo arithmetic for unsigned
> types, 65535 + 1 = 0. So zero could represent the "one past last" pointer.
>
> If we subtract 1 from 0, we're left with 65535.
>
> It would be possible to have a system where a pointer to "one past last"
is
> null, and still satisfy the following:
>
>     char *p = &last_element + 1;
>
>     char *p_last_element = p - 1;

There seems to be a draft of a future version of the standard available
on the internet which says that: "If both the pointer operand and the
result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an
overflow; otherwise, the behavior is undefined." This would make your
example yield undefined behaviour.

This text, like the one quoted by Heinz Ozwirk, can allegedly be found
in 6.5.6/8, a paragraph that does not seem to exist in my version of
the standard. I found the information here:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_221.htm

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Frederick Gotham <fgothamNO@SPAM.com>
Date: Wed, 9 Aug 2006 09:56:15 CST
Raw View
Eisenbart posted:

>>     char *p = &last_element + 1;
>>
>>     char *p_last_element = p - 1;
>
> There seems to be a draft of a future version of the standard available
> on the internet which says that: "If both the pointer operand and the
> result point to elements of the same array object, or one past the last
> element of the array object, the evaluation shall not produce an
> overflow; otherwise, the behavior is undefined." This would make your
> example yield undefined behaviour.


On the contrary, it would make it yield perfectly defined behaviour. (Perhaps
you read it wrong?)

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Wed, 9 Aug 2006 10:45:04 CST
Raw View
johnchx2@yahoo.com wrote:
> Frederick Gotham wrote:
>
> > No, not impossible. Let's say we have a 16-Bit unsigned integer (with no
> > padding). It has 65536 unique values, and can store values in the range 0
> > through 65535.
> >
> > If 65535 were to represent the last available byte, then 65535 + 1 would
> > represent the "one past last" byte. Obeying modulo arithmetic for unsigned
> > types, 65535 + 1 = 0. So zero could represent the "one past last" pointer.
>
> But how would this hypothetical implementation comply with 4.10/1,
> which says that the null pointer value (the result of converting the
> null pointer constant to a pointer type) is distinguishable from every
> other value of pointer type?

I don't have my copy of the C++ standard available right now. Do you?
Could you re-check the wording of that section? What you're saying
doesn't match what I remember, which is that a null pointer must
compare unequal to any pointer to an object. I do have a copy of the C
standard available, and that is what it says. I don't remember this as
being one of the (many) areas where the two languages differ.

This means that if the implementation designates 0 as a null pointer,
there can't be any object allocated at address 0. Therefore, 65535+1
won't be pointing at an object, and therefore can legally be a null
pointer.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "ThosRTanner" <ttanner2@bloomberg.net>
Date: Wed, 9 Aug 2006 10:43:02 CST
Raw View
johnc...@yahoo.com wrote:
> Frederick Gotham wrote:
>
> > No, not impossible. Let's say we have a 16-Bit unsigned integer (with no
> > padding). It has 65536 unique values, and can store values in the range 0
> > through 65535.
> >
> > If 65535 were to represent the last available byte, then 65535 + 1 would
> > represent the "one past last" byte. Obeying modulo arithmetic for unsigned
> > types, 65535 + 1 = 0. So zero could represent the "one past last" pointer.
>
> But how would this hypothetical implementation comply with 4.10/1,
> which says that the null pointer value (the result of converting the
> null pointer constant to a pointer type) is distinguishable from every
> other value of pointer type?

I don't think 4.10/1 is achievable then. The general idea of a virtual
machine is that all memory addresses are accessible. Given a 32-bit VM
machine, there is no particular reason why address 0xffffffff shouldn't
contain a valid array of 1 byte. Taking a pointer to it, is valid,
adding one is valid, but the resultant address is zero, which is
indistinguishable from yer actual null pointer value.

I can think of some hardware I've worked on where "interesting data" is
kept in that sort of area as well.

> I would think that the purpose of this requirement is to outlaw any
> implementation in which valid pointer arithmetic can produce a result
> that "collides" with the null pointer value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: johnchx2@yahoo.com
Date: Wed, 9 Aug 2006 11:35:07 CST
Raw View
kuyper@wizard.net wrote:
> johnchx2@yahoo.com wrote:
> > But how would this hypothetical implementation comply with 4.10/1,
> > which says that the null pointer value (the result of converting the
> > null pointer constant to a pointer type) is distinguishable from every
> > other value of pointer type?
>
> I don't have my copy of the C++ standard available right now. Do you?
> Could you re-check the wording of that section? What you're saying
> doesn't match what I remember, which is that a null pointer must
> compare unequal to any pointer to an object.

Quoting: "A null pointer constant can be converted to a pointer type;
the result is the null pointer value of that type and is
distinguishable from every other value of pointer to object or pointer
to function type."

The key thing is that the null pointer value is distinct from any other
value with pointer *type*, regardless of whether the pointer points to
an actual object.  "Off the end" pointers have pointer-to-object
*type*, even though they point to no object.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: mscottschilling@hotmail.com ("Mike Schilling")
Date: Thu, 10 Aug 2006 02:04:10 GMT
Raw View
"ThosRTanner" <ttanner2@bloomberg.net> wrote in message
news:1155124207.150355.30050@i3g2000cwc.googlegroups.com...
>
> johnc...@yahoo.com wrote:
>> Frederick Gotham wrote:
>>
>> > No, not impossible. Let's say we have a 16-Bit unsigned integer (with
>> > no
>> > padding). It has 65536 unique values, and can store values in the range
>> > 0
>> > through 65535.
>> >
>> > If 65535 were to represent the last available byte, then 65535 + 1
>> > would
>> > represent the "one past last" byte. Obeying modulo arithmetic for
>> > unsigned
>> > types, 65535 + 1 = 0. So zero could represent the "one past last"
>> > pointer.
>>
>> But how would this hypothetical implementation comply with 4.10/1,
>> which says that the null pointer value (the result of converting the
>> null pointer constant to a pointer type) is distinguishable from every
>> other value of pointer type?
>
> I don't think 4.10/1 is achievable then. The general idea of a virtual
> machine is that all memory addresses are accessible. Given a 32-bit VM
> machine, there is no particular reason why address 0xffffffff shouldn't
> contain a valid array of 1 byte. Taking a pointer to it, is valid,
> adding one is valid, but the resultant address is zero, which is
> indistinguishable from yer actual null pointer value.
>
> I can think of some hardware I've worked on where "interesting data" is
> kept in that sort of area as well.

There's no requirement that a null pointer be the bit pattern "all zeros".
C++ can reserve addresses (say) 4 and 5, ensuring that no C++-addressable
data is stored there, with 5 being the null pointer value and never being a
one-past-the-end value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Matthias Hofmann" <hofmann@anvil-soft.com>
Date: Thu, 10 Aug 2006 08:49:17 CST
Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> schrieb im Newsbeitrag
news:JAmCg.12450$j7.321571@news.indigo.ie...
> Eisenbart posted:
>
> >>     char *p = &last_element + 1;
> >>
> >>     char *p_last_element = p - 1;
> >
> > There seems to be a draft of a future version of the standard available
> > on the internet which says that: "If both the pointer operand and the
> > result point to elements of the same array object, or one past the last
> > element of the array object, the evaluation shall not produce an
> > overflow; otherwise, the behavior is undefined." This would make your
> > example yield undefined behaviour.
>
>
> On the contrary, it would make it yield perfectly defined behaviour.
(Perhaps
> you read it wrong?)

What I wanted to say is that in your example, there cannot be an
overflow, so a pointer to "one past last" cannot result in a null
pointer.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Thu, 10 Aug 2006 08:49:37 CST
Raw View
Frederick Gotham wrote:
> May I propose, in the next Standard, that it be explicitly stated whether a
> pointer to "one past the last element of an array" can be a null pointer.
>
> There's been quite a bit of controversy about this in the past, and no solid
> answer has ever been given. So maybe it would be better if the Standard
> spelled it out in black-and-white. Either:
>

Well, a new discussion about that issue appears on this thread... It
proves that it can be unclear for advanced programmers knowing well the
standard.

So, I think it is a very good idea to specify that, explicitly, either
in a new paragraph, or as a footnote of a paragraph that the standard
assume as being normative on the issue.


>     (1) A pointer to one past the last element of an array shall not be a
> null pointer.
>
> or:
>
>     (2) This Standard imposes no restriction whereby a pointer to one past
> the last element of an array shall not be a null pointer.
>
> Something like that.
>
Or, a third possibility:
(3) It is implementation-defined whether a pointer to one past the last
element of an array can be a null pointer.

Anyway, I think that something must be written about that issue...

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Thu, 10 Aug 2006 14:20:41 GMT
Raw View
Matthias Hofmann posted:

>> On the contrary, it would make it yield perfectly defined behaviour.
> (Perhaps
>> you read it wrong?)
>
> What I wanted to say is that in your example, there cannot be an
> overflow, so a pointer to "one past last" cannot result in a null
> pointer.


If we have 32-Bit pointers, and if the address of the last element in the
array is 0xFFFFFFFF, then the address of "one past last" would be 0.

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: no.spam@no.spam.com (Maciej Sobczak)
Date: Thu, 10 Aug 2006 14:43:02 GMT
Raw View
ThosRTanner wrote:

> I don't think 4.10/1 is achievable then. The general idea of a virtual
> machine is that all memory addresses are accessible.

But C++ is not forced to use all of them.
The implementation is allowed to explicitly allocate more than is needed
to accommodate the past-the-end pointer value.
Such an implementation will never allocate anything starting at
0xffffffff, even if you ask for an array of 1 byte - exactly to ensure
the room for that additional past-the-end address.


--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]