Topic: ptrdiff_t is faulty?
Author: Michiel.Salters@tomtom.com
Date: Wed, 6 Dec 2006 11:44:42 CST Raw View
kuyper@wizard.net schreef:
> two pointers must
> compare equal if and only if they point to the same object. That's
> pretty difficult to do unless pointers to distinct objects have
> distinct representations.
The "only if" bit is wrong. Proof:
int p,q;
&p==&q;
These may compare equal (unspecified by the standard) which contradicts
your statement that they compare equal only if they point to the same
object.
HTH,
Michiel Salters
---
[ 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, 6 Dec 2006 15:11:55 CST Raw View
Michiel.Salters@tomtom.com wrote:
> kuyper@wizard.net schreef:
>
> > two pointers must
> > compare equal if and only if they point to the same object. That's
> > pretty difficult to do unless pointers to distinct objects have
> > distinct representations.
>
> The "only if" bit is wrong. Proof:
> int p,q;
> &p==&q;
>
> These may compare equal (unspecified by the standard) which contradicts
> your statement that they compare equal only if they point to the same
> object.
Would you care to explain that assertion? There are complications that
I glossed over, when one of the pointers is null or points one past the
end of an array. As a result, &p+1 and &q are allowed to compare equal,
but I would argue that this is true because &p+1 might happen to point
at the same object as &q, even though you can't write code with defined
behavior which demonstrates that fact. I could rescue my original claim
from these complications by changing it to say that two valid non-null
pointers which point at objects compare equal if and only if they point
to the same object. That modification doesn't invalidate my conclusion.
But you asserted that &p and &q could compare equal, which involves
none of the complicating factors. Offhand, I can't figure out any
plausible basis for that assertion.
---
[ 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: Thu, 7 Dec 2006 00:17:51 CST Raw View
Michiel.Salters@tomtom.com wrote:
> kuyper@wizard.net schreef:
>
> > two pointers must
> > compare equal if and only if they point to the same object. That's
> > pretty difficult to do unless pointers to distinct objects have
> > distinct representations.
>
> The "only if" bit is wrong. Proof:
> int p,q;
> &p==&q;
>
> These may compare equal (unspecified by the standard) which contradicts
> your statement that they compare equal only if they point to the same
> object.
The actual rule is:
"Two pointers of the same type compare equal if and only if they are
both null, both point to the same function, or both represent the same
address." [5.10/1]
(An "address", by the way, uniquely identifies a byte in memory).
Since p and q are individually-declared objects of the same type, they
are two distinct objects. Therefore their addresses cannot compare
equal.
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: kuyper@wizard.net
Date: Thu, 7 Dec 2006 00:24:34 CST Raw View
Michiel.Salters@tomtom.com wrote:
> kuyper@wizard.net schreef:
>
> > two pointers must
> > compare equal if and only if they point to the same object. That's
> > pretty difficult to do unless pointers to distinct objects have
> > distinct representations.
>
> The "only if" bit is wrong. Proof:
The "only if" is a direct quote from the standard, though I left out a
few details that aren't relevant to my earlier point, nor to your
supposed counter-example:
> int p,q;
> &p==&q;
>
> These may compare equal (unspecified by the standard) which contradicts
> your statement that they compare equal only if they point to the same
> object.
Section 5.10p1 says "Two pointers of the same type compare equal if and
only if they are both null, both point to the same object or function
or both point one past the end of the same array."
&p and &q have the same type. Neither one is null. Neither one points
one past the end of an array, they don't point at the same object, and
neither one points at a function. How could they compare equal?
---
[ 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: Wed, 29 Nov 2006 00:21:53 GMT Raw View
kuyper@wizard.net writes:
> Frederick Gotham wrote:
>> Still though, every object must have a unique address, even when converted
>> to void*.
>
> More accurately, each object must have one or more addresses that it
> doesn't share with any non-overlapping object. It's not restricted to
> having only one address, so long as pointers pointing to the different
> addresses all compare equal to each other.
This is getting into English semantics rather than C++ semantics.
For an object obj of type t, there may be multiple valid
representations of type t*, each of which will compare equal to &obj.
Are these multiple addresses, or are they multiple representations of
the same unique address?
I have no strong preference for one answer or the other, but that
seems to be the question about which you're implicitly disagreeing.
--
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: kuyper@wizard.net
Date: Wed, 29 Nov 2006 09:56:59 CST Raw View
Keith Thompson wrote:
> kuyper@wizard.net writes:
> > Frederick Gotham wrote:
> >> Still though, every object must have a unique address, even when converted
> >> to void*.
> >
> > More accurately, each object must have one or more addresses that it
> > doesn't share with any non-overlapping object. It's not restricted to
> > having only one address, so long as pointers pointing to the different
> > addresses all compare equal to each other.
>
> This is getting into English semantics rather than C++ semantics.
>
> For an object obj of type t, there may be multiple valid
> representations of type t*, each of which will compare equal to &obj.
>
> Are these multiple addresses, or are they multiple representations of
> the same unique address?
As I see it, those pointers can have different representations, because
those representations can identify different addresses which represent
the same unique memory location. The other alternative would be
described as pointers containing multiple representations of the same
unique address which identifies a memory location, and that doesn't
make sense to me. However, since the standard doesn't define "address",
and doesn't impose any requirements in terms of the concept, any
discussion on that point is, as you say, a discussion of English
semantics, rather than C++ semantics.
> I have no strong preference for one answer or the other, but that
> seems to be the question about which you're implicitly disagreeing.
Possibly; but I doubt it. I got the distinct impression that Frederick
was not thinking about the possibilities of there being multiple
representations. I don't think it has anything to do with what those
multiple representations are called, or what you call the unique thing
that they represent.
---
[ 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, 27 Nov 2006 02:40:32 GMT Raw View
"Bo Persson":
>> Now all we need to know is what a "total order" is.
>
> It is an ordering that is stronger than weak and partial ordering. :-)
> Section 25.3/4 says so.
>
> Unfortunately, what could have been a definition of strict ordering is
> just a note. So formally perhaps we don't know.
I am still bewildered as to how std::less could give a different reading to
operator<.
--
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, 27 Nov 2006 02:41:13 GMT Raw View
James Kanze:
> In a legal C++ program. If the program has undefined behavior
> elsewhere, all bets are off.
That was an unspoken pre-requisite.
> And you have to be careful about how you understand "point to
> different objects":
>
> int a ;
> int b[ 1 ] ;
>
> assert( &a != b + 1 ) ;
>
> is not guaranteed.
Yes I realise that. The pointer to "one past last" may be equal to null, or
it may be equal to the address of another object, or it may be unique.
Basically, when dealing with a pointer to "one past last", the only
guarantee you're given is that arithmetic will work correctly on it.
Still though, every object must have a unique address, even when converted
to void*.
> But only because b+1 doesn't point to an
> object. A pointer to one past the end of an array may point to
> another object as well.
Indeed.
> It depends. If this occurs in a 100% conformant program, with
> no undefined behavior, true (although see the problem with
> pointers one past the end).
You can assume, when I engage in discussions of this nature, a pre-
requisite that the program contains no other undefined behaviour.
> If the program has even the
> slightest undefined behavior (accessing a union other than
> through the last member written, accessing through a pointer
> resulting from a reinterpret_cast,
Don't be so quick to thrash reinterpret_cast:
unsigned i;
char unsigned *p = reinterpret_cast<char unsigned*>(&i);
char unsigned const *const pover = p + sizeof i;
do *p++ = 0; while (pover!=p);
assert( !i ); /* Must not fail! */
> incrementing beyond the end
> of an array, etc.), then all bets are off. For that matter, on
> an 8086, given:
>
> int scalar ;
> int array[ 8 ] ;
> int* ps = &s ;
> int* pa = array + 8 ;
>
> pa could actually point to scalar, but not compare equal to ps.
Again, these discussions are meaningless unless we have the pre-requisite
that the rest of the program is perfectly well defined.
--
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, 27 Nov 2006 02:42:42 GMT Raw View
James Kanze:
>> That leads to a paradoxical conclusion that the loop
>> for(char const (*a_ptr)(*a_buf); a_ptr < a_buf[01]; ++a_ptr);
>> can be faster than the loop
>> for(char const (*a_ptr)(*a_buf); a_ptr != a_buf[01]; ++a_ptr);
>> Usually the second loop is considered faster and the first one safer.
>
> By whom? I've never encountered an architecture where the
> second was faster; on most architectures, they're the same; on
> segmented architectures, the first is potentially faster, at
> least.
Look at the processing that needs to be done. Let's take two 8-Bit numbers:
1001 1011
1011 1110
To perform operator!=, all we need to do is read from left to right (or
right to left, it doesn't matter) and check that corresponding bits match.
Something like:
(Here's some imaginary code)
char unsigned a = 82, b = 74;
BitPtr p = &a, q = &b, pover = p + CHAR_BIT;
do if (*p++ != *q++) return true; while (pover!=p);
return false;
To peform operator<, we need to read from left to right. When two bits
don't match, we've to check which operand had the set bit, something like:
do if (*p != *q++)
{
if (*p) return true;
else return false;
}
while (pover!=++p);
return false;
By this understanding, operator< need to peform one more check than
operator!=.
--
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: Sun, 26 Nov 2006 20:42:18 CST Raw View
Frederick Gotham wrote:
> Bo Persson:
>
> > No, I meant std::less and operator<. :-)
> >
> > 20.5.7/8 says
> > "For templates greater, less, greater_equal, and less_equal, the
> > specializations for any pointer type yield a total order, even if the
> > built-in operators <, >, <=, >= do not."
>
>
> Now all we need to know is what a "total order" is.
It's a standard concept in mathematics, and therefore doesn't need to
be defined by the C++ standard itself. I did a quick search at
www.ask.com, and the first good answer I found was
<http://www.knowledgerush.com/kr/encyclopedia/Total_order/>, but
there's many more to choose from.
---
[ 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: Sun, 26 Nov 2006 20:42:28 CST Raw View
Ron Natalie wrote:
> kuyper@wizard.net wrote:
>
> >> No, I'm not saying that. What I'm saying is that if you use operator== or
> >> operator!= to compare pointers which point to different objects, then they
> >> must NOT compare equal. Never. Never ever.
> >
> > That's not a problem that can occur in a segmented architecture.
>
> Umm, yes it is. If it is a problem which your architecture, you need
> to make sure your compiler outputs appropriate code.
I'm sorry; that's not quite what I meant to say. What I meant to say is
that the fact that a platform uses segmented addresses doesn't mean
that it has to have that problem. It's obviously possible to implement
== and != incorrectly on any platform, and a platform with a segmented
address architecture does provide an extra opportunity to do so; but
it's quite straightforward to implement them correctly, even on such
platforms..
---
[ 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: Sun, 26 Nov 2006 20:41:22 CST Raw View
"Kri tof elechovski" wrote:
> When you compare addresses of members of a union, at most one of them
> exists;
> you can assign a value to it to bring it to life.
> In other words, one of the resulting pointers is write-only;
> there is no object pointed to, it is merely a placeholder.
> In the second case, the objects are related because one is a member of the
> other.
> Therefore the principle under discussion
> must be restricted to mereologically unrelated living objects.
The rule is simple: different objects of the same type must have
different addresses - while objects of different types may (and often
do) share the same address.
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: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 26 Nov 2006 20:47:29 CST Raw View
Frederick Gotham wrote:
> Bo Persson:
>
> > No, I meant std::less and operator<. :-)
> >
> > 20.5.7/8 says
> > "For templates greater, less, greater_equal, and less_equal, the
> > specializations for any pointer type yield a total order, even if the
> > built-in operators <, >, <=, >= do not."
>
> Now all we need to know is what a "total order" is.
A "total order" on set X is any binary relation on X that is
antisymmetric, transitive, and total.
http://en.wikipedia.org/wiki/Total_order
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: kuyper@wizard.net
Date: Sun, 26 Nov 2006 23:15:30 CST Raw View
Frederick Gotham wrote:
> "Bo Persson":
>
> >> Now all we need to know is what a "total order" is.
> >
> > It is an ordering that is stronger than weak and partial ordering. :-)
> > Section 25.3/4 says so.
> >
> > Unfortunately, what could have been a definition of strict ordering is
> > just a note. So formally perhaps we don't know.
>
>
> I am still bewildered as to how std::less could give a different reading to
> operator<.
On a segment-offset platform, the implemention could choose to ensure
that all pointers into or one past the end of a given object will share
the same segment. That allows operator< to be implemented simply as a
comparison of the offsets. This will give meaningless results when the
segment values are different, but that's permitted, since the result of
such comparisons are unspecified. However, since std::less<> is
required to establish a total order, it must compare both the segment
and the offset in order to determine what result it produces; if the
architecture allows overlapping segments, it will also have to
normalize the addresses before the comparison.
This means that operator< is faster, making it the preferred option
when comparing pointers known to point within the same object.
std::less<> is slower, but since it guarantees a total order, it's more
appropriate when, for instance, you need sort a container of unrelated
pointers, or create an associative container when the keys are
unrelated pointers.
While that example is specific to segment-offset platforms, the
conclusion is not. When std::less<> produces different results than
operator<, it will normally be because the constraint of having to
produce a total order means that it's been less efficiently implemented
than operator<. If ensuring a total order could be implemented equally
efficiently, there'd be no point implementing operator< differently
from std::less<>.
---
[ 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: Sun, 26 Nov 2006 23:16:13 CST Raw View
Frederick Gotham wrote:
.
> Still though, every object must have a unique address, even when converted
> to void*.
More accurately, each object must have one or more addresses that it
doesn't share with any non-overlapping object. It's not restricted to
having only one address, so long as pointers pointing to the different
addresses all compare equal to each other.
---
[ 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, 27 Nov 2006 15:42:40 GMT Raw View
:
> On a segment-offset platform, the implemention could choose to ensure
> that all pointers into or one past the end of a given object will share
> the same segment. That allows operator< to be implemented simply as a
> comparison of the offsets. This will give meaningless results when the
> segment values are different, but that's permitted, since the result of
> such comparisons are unspecified.
Undefined rather than unspecified, I think. "Unspecified" would suggest
that it may yield either true or false. "Undefined" would suggest that the
computer can expode if it wants to.
> However, since std::less<> is
> required to establish a total order, it must compare both the segment
> and the offset in order to determine what result it produces; if the
> architecture allows overlapping segments, it will also have to
> normalize the addresses before the comparison.
Oh right. So basically, "std::less" is like operator<, except it doesn't
invoke undefined behaviour if the addresses are unrealted.
> This means that operator< is faster, making it the preferred option
> when comparing pointers known to point within the same object.
> std::less<> is slower, but since it guarantees a total order, it's more
> appropriate when, for instance, you need sort a container of unrelated
> pointers, or create an associative container when the keys are
> unrelated pointers.
Yes, but I don't see why you'd want to do that. If addresses are unrelated,
then I don't see any reason to compare them.
> While that example is specific to segment-offset platforms, the
> conclusion is not. When std::less<> produces different results than
> operator<, it will normally be because the constraint of having to
> produce a total order means that it's been less efficiently implemented
> than operator<. If ensuring a total order could be implemented equally
> efficiently, there'd be no point implementing operator< differently
> from std::less<>.
I understand, thanks.
--
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: "Greg Herlihy" <greghe@pacbell.net>
Date: Mon, 27 Nov 2006 11:23:24 CST Raw View
Frederick Gotham wrote: :
>
> > On a segment-offset platform, the implemention could choose to ensure
> > that all pointers into or one past the end of a given object will share
> > the same segment. That allows operator< to be implemented simply as a
> > comparison of the offsets. This will give meaningless results when the
> > segment values are different, but that's permitted, since the result of
> > such comparisons are unspecified.
>
> Undefined rather than unspecified, I think. "Unspecified" would suggest
> that it may yield either true or false. "Undefined" would suggest that the
> computer can expode if it wants to.
There are no relational comparisons with undefined behavior in C++. The
outcome of certain pointer comparisons is unspecified - meaning that
the comparison will evaluate to either true or false - but the result
does not need to be consistent.
> > However, since std::less<> is
> > required to establish a total order, it must compare both the segment
> > and the offset in order to determine what result it produces; if the
> > architecture allows overlapping segments, it will also have to
> > normalize the addresses before the comparison.
>
> Oh right. So basically, "std::less" is like operator<, except it doesn't
> invoke undefined behaviour if the addresses are unrealted.
The less-than operator does not invoke undefined behavior either. But
an unspecified result when comparing pointers does not impose a total
ordering on the pointers being compared - meaning that the less-than
operator could not be used to sort a set of pointers.
> > This means that operator< is faster, making it the preferred option
> > when comparing pointers known to point within the same object.
> > std::less<> is slower, but since it guarantees a total order, it's more
> > appropriate when, for instance, you need sort a container of unrelated
> > pointers, or create an associative container when the keys are
> > unrelated pointers.
>
> Yes, but I don't see why you'd want to do that. If addresses are unrelated,
> then I don't see any reason to compare them.
Then how would you store pointers in a std::map, for example?
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: kuyper@wizard.net
Date: Mon, 27 Nov 2006 11:23:17 CST Raw View
Frederick Gotham wrote:
> :
>
> > On a segment-offset platform, the implemention could choose to ensure
> > that all pointers into or one past the end of a given object will share
> > the same segment. That allows operator< to be implemented simply as a
> > comparison of the offsets. This will give meaningless results when the
> > segment values are different, but that's permitted, since the result of
> > such comparisons are unspecified.
>
>
> Undefined rather than unspecified, I think. "Unspecified" would suggest
> that it may yield either true or false. "Undefined" would suggest that the
> computer can expode if it wants to.
My copy of the C++ standard is at home, and I'm not, so I can't check
right now, but you may be right. Either way, the optimization I
describe is legal.
> Oh right. So basically, "std::less" is like operator<, except it doesn't
> invoke undefined behaviour if the addresses are unrealted.
Exactly.
> > This means that operator< is faster, making it the preferred option
> > when comparing pointers known to point within the same object.
> > std::less<> is slower, but since it guarantees a total order, it's more
> > appropriate when, for instance, you need sort a container of unrelated
> > pointers, or create an associative container when the keys are
> > unrelated pointers.
>
>
> Yes, but I don't see why you'd want to do that. If addresses are unrelated,
> then I don't see any reason to compare them.
I'm not sure I follow that. What strikes you as unreasonable about
putting unrelated pointers into an associative container as key values?
As far as I know (which unfortunately isn't much, since my profession
experience is in C, not C++), this is a very commonly used technique.
In many cases, it makes more sense to sort based upon the pointed-at
value, than by the pointer value, but not always.
It also strikes me as perfectly reasonable to put unrelated T* values
into a sequence container, such as std::vector<>, and sorting that
sequence using std::less<T*> as the comparison operator, so that it can
be quickly searched multiple times for particular pointer values by
doing a binary search with std::less<T*> as the comparison operator.
---
[ 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: usenet-nospam@nmhq.net (Niklas Matthies)
Date: Mon, 27 Nov 2006 18:08:26 GMT Raw View
On 2006-11-27 02:42, Frederick Gotham wrote:
> James Kanze:
>
>>> That leads to a paradoxical conclusion that the loop
>>> for(char const (*a_ptr)(*a_buf); a_ptr < a_buf[01]; ++a_ptr);
>>> can be faster than the loop
>>> for(char const (*a_ptr)(*a_buf); a_ptr != a_buf[01]; ++a_ptr);
>>> Usually the second loop is considered faster and the first one safer.
>>
>> By whom? I've never encountered an architecture where the second
>> was faster; on most architectures, they're the same; on segmented
>> architectures, the first is potentially faster, at least.
>
> Look at the processing that needs to be done. Let's take two 8-Bit
> numbers:
:
> By this understanding, operator< need to peform one more check than
> operator!=.
For types that are implemented in hardware that usually doesn't
matter, since the "checks" are performed by circuits in parallel,
and both operations simply take one cycle.
-- Niklas Matthies
---
[ 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, 27 Nov 2006 21:37:50 GMT Raw View
Greg Herlihy:
>> Undefined rather than unspecified, I think. "Unspecified" would suggest
>> that it may yield either true or false. "Undefined" would suggest that
>> the computer can expode if it wants to.
>
> There are no relational comparisons with undefined behavior in C++. The
> outcome of certain pointer comparisons is unspecified - meaning that
> the comparison will evaluate to either true or false - but the result
> does not need to be consistent.
Sorry, you're right.
5.9.2
If two pointers p and q of the same type point to different objects
that are not members of the same object or elements of the same
array or to different functions, or if only one of them is null, the
results of p<q, p>q, p<=q, and p>=q are unspecified.
>> Oh right. So basically, "std::less" is like operator<, except it
>> doesn't invoke undefined behaviour if the addresses are unrealted.
>
> The less-than operator does not invoke undefined behavior either. But
> an unspecified result when comparing pointers does not impose a total
> ordering on the pointers being compared - meaning that the less-than
> operator could not be used to sort a set of pointers.
I see. Is there any portable way to implement std::less? The following has
unspecified behaviour with unrelated pointers:
template<class T>
bool less(T const &a,T const &b)
{
return a < b;
}
--
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: Mon, 27 Nov 2006 16:07:36 CST Raw View
Frederick Gotham wrote:
.
> I see. Is there any portable way to implement std::less?
I don't believe that there is.
---
[ 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: giecrilj@stegny.2a.pl ("Kristof Zelechovski")
Date: Mon, 27 Nov 2006 22:33:45 GMT Raw View
Uzytkownik "Greg Herlihy" <greghe@pacbell.net> napisal w wiadomosci=20
news:1164575494.139734.173520@f16g2000cwb.googlegroups.com...
>
> "Kri=A8tof =B4elechovski" wrote:
>> When you compare addresses of members of a union, at most one of them
>> exists;
>> you can assign a value to it to bring it to life.
>> In other words, one of the resulting pointers is write-only;
>> there is no object pointed to, it is merely a placeholder.
>> In the second case, the objects are related because one is a member of=
=20
>> the
>> other.
>> Therefore the principle under discussion
>> must be restricted to mereologically unrelated living objects.
>
> The rule is simple: different objects of the same type must have
> different addresses - while objects of different types may (and often
> do) share the same address.
It does not cover the case of union U { int m_a, m_b; };
Chris=20
---
[ 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, 27 Nov 2006 23:31:03 GMT Raw View
Frederick Gotham wrote:
> Greg Herlihy:
>
>>> Undefined rather than unspecified, I think. "Unspecified" would suggest
>>> that it may yield either true or false. "Undefined" would suggest that
>>> the computer can expode if it wants to.
>> There are no relational comparisons with undefined behavior in C++. The
>> outcome of certain pointer comparisons is unspecified - meaning that
>> the comparison will evaluate to either true or false - but the result
>> does not need to be consistent.
>
>
> Sorry, you're right.
>
> 5.9.2
> If two pointers p and q of the same type point to different objects
> that are not members of the same object or elements of the same
> array or to different functions, or if only one of them is null, the
> results of p<q, p>q, p<=q, and p>=q are unspecified.
>
>
>>> Oh right. So basically, "std::less" is like operator<, except it
>>> doesn't invoke undefined behaviour if the addresses are unrealted.
>> The less-than operator does not invoke undefined behavior either. But
>> an unspecified result when comparing pointers does not impose a total
>> ordering on the pointers being compared - meaning that the less-than
>> operator could not be used to sort a set of pointers.
>
>
> I see. Is there any portable way to implement std::less?
No, but there doesn't need to be; that's why it exists.
> The following has
> unspecified behaviour with unrelated pointers:
>
> template<class T>
> bool less(T const &a,T const &b)
> {
> return a < b;
> }
>
Yes, but the implementation itself is allowed to rely on unspecified or
undefined behavior.
--
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, 24 Nov 2006 18:53:59 GMT Raw View
Bo Persson:
> It can be even worse, if we allow the segments to overlap (like in x86
> real mode). Then many combinations of segment:offset pairs may infact
> point at the same location.
>
> That's one reason for C++ to allow p==q to be different from
> std::equal(p,q). The latter must normalize the pointers, if needed.
Did you mean to say "equal_to" instead of "equal"?
Assuming "p" and "q" are pointers:
int a, b, *p=&a, *q=&b;
Regardless of how an object is allocated, an object must have a unique
address among all other objects.
If we want to check for equality/inequality with pointers, we simply use ==
and !=.
Why would "equal_to" yield different results to simple == and !=?
Also, If I'm not mistaken, "std::equal" is a different animal altogether
which is used for checking the equality of elements in a container, e.g.:
vector<int> a,b;
equal(a.begin(),a.end(),b.begin());
--
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: Fri, 24 Nov 2006 18:54:37 GMT Raw View
Pete Becker:
> What, exactly, do you claim is forbidden?
Give me two pointers of any type. If they are the addresses of different
objects, then they must not be equal -- they must be unique:
(Let's forget about inheritance for the moment.)
template<class A,class B>
bool PtrEquality(A const *const pa,B const *const pb)
{
return (void const volatile*)pa == (void const volatile*)pb;
}
This should _never_ return true for any of the following:
int a;
double b;
char c;
int main()
{
int d;
double e;
char f;
int &g = *new int;
double &h = *new double;
char &f = *new char;
PtrEquality(a,b);
PtrEquality(c,b);
/* No combination of letters a through f should return true */
}
--
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: Fri, 24 Nov 2006 18:55:00 GMT Raw View
Hyman Rosen:
> In the old days, there were
> memory models under which a pointer was a 32-bit object
> divided into two 16-bit pieces, a segment and an offset.
> When you compared p1 == p2, the code generated a comparison
> of the entire 32 bits, but when you compared p1 < p2 it
> compared only the offsets, because objects were limited to
> 64K and pointers into the same object always had the same
> segment part.
Magnificent example! Easily understood as follows:
enum SegmentID { Seg1, Seg2, Seg3, Seg4 };
struct Pointer {
SegmentID seg;
unsigned address;
};
bool Equal(Pointer const a,Pointer const b)
{
bool const seg_equality = a.seg==b.seg;
bool const address_equality = a.address==b.address;
return seg_equality && address_equality; /* Checks both of them */
}
bool Greater(Pointer const a,Pointer const b)
{
bool const address_equality == b.address > a.address;
return address_equality; /* Doesn't make sure of same segment! */
}
--
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: giecrilj@stegny.2a.pl ("K i tof elechovski")
Date: Fri, 24 Nov 2006 18:55:10 GMT Raw View
U=BFytkownik "Bo Persson" <bop@gmb.dk> napisa=B3 w wiadomo=B6ci=20
news:4sm9u2F10ghauU1@mid.individual.net...
> Keith Thompson wrote:
>
>> This could plausibly happen in, say, a segmented architecture, where
>> an address consists of a segment number and an offset within the
>> segment. "=3D=3D" and "!=3D" would have to compare both components of
>> each address. "<" et al can *assume* that both operands point
>> within the same object, and therefore that they're in the same
>> segment. Thus two pointers with different segment numbers but
>> (coincidentally) identical offsets would appear to be unequal using
>> "=3D=3D" and "!=3D", but (falsely) equal using "<=3D" and ">=3D".
>
> It can be even worse, if we allow the segments to overlap (like in x86=20
> real mode). Then many combinations of segment:offset pairs may infact=20
> point at the same location.
>
> That's one reason for C++ to allow p=3D=3Dq to be different from=20
> std::equal(p,q). The latter must normalize the pointers, if needed.
>
>
How is it possible to get such anomalous pointers in pure C++
(are equal but do not compare equal)? (MK_FP is not pure C++).
When you take the address of an object,
the compiler should be consistent about what the segment is.
When you create the object on the heap, you get one unaliased pointer;
the underlying object may be accessed only by that pointer
and all copies of it should compare equal.
Chris=20
---
[ 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: Pete Becker <pete@versatilecoding.com>
Date: Fri, 24 Nov 2006 14:05:40 CST Raw View
Frederick Gotham wrote:
> Pete Becker:
>
>> What, exactly, do you claim is forbidden?
>
>
> Give me two pointers of any type. If they are the addresses of different
> objects, then they must not be equal -- they must be unique:
>
Sigh. Yes, that's obviously true. You've snipped the original context,
however, which was:
Frederick Gotham wrote:
> "Bo Persson":
>
>> It was all *very* common at the time the C++ standard was first
drafted. Until Windows 95 came around, most of us used segmented memory,
where pointers into different segments could not be compared without a
lot of overhead. Different segmentation models, had their own specific
problems.
>>
>> Here is one compiler that still supports this:
>>
>> http://www.digitalmars.com/ctg/ctgMemoryModel.html
>
>
> This is forbidden by the C++ Standard. Every object must have a
unique > address. E.g.:
So, you seem to be claiming that it is impossible to guarantee that the
addresses of different objects compare unequal on segmented
architectures. That's simply wrong.
--
-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
---
[ 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: Fri, 24 Nov 2006 21:09:34 GMT Raw View
In article <4sm9u2F10ghauU1@mid.individual.net>, Bo Persson <bop@gmb.dk>
writes
>That's one reason for C++ to allow p==q to be different from
>std::equal(p,q). The latter must normalize the pointers, if needed.
I think the former must also. If p and q point to the same object the
result of p==q is required to be true.
--
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: kuyper@wizard.net
Date: Fri, 24 Nov 2006 15:11:45 CST Raw View
Pete Becker wrote:
> kuyper@wizard.net wrote:
> > Pete Becker wrote:
.
> >> What, exactly, do you claim is forbidden? Segmented addressing is not a
> >> barrier to a conforming implementation of C++. There is no requirement
> >> that every object have a unique hardware address, just that every time
> >> you say &i for the same i you always get the same value.
> >
> > There's a few more requirement than just that one; two pointers must
> > compare equal if and only if they point to the same object. That's
> > pretty difficult to do unless pointers to distinct objects have
> > distinct representations.
> >
>
> But, again, that has nothing to do with whether the hardware allows
> multiple representations of the same address.
I'm sorry - I just realized that I'd misinterpreted what you were
saying. When you said that "there is no requirement that every object
have a unique hardware address", I thought you were saying that the
address didn't have to be unique to that object; that it could be
shared by multiple objects. After all, that's what Frederick Gotham was
talking about: his example code involved comparing the values of
pointers to different objects.
I see now that you meant that the address didn't have to be the only
address for that object. That's perfectly true, but not really relevant
as a response to Gotham's message. His example did not involve
comparing the repserentations of multiple pointers to the same object.
The relevant response is to point out that he's wrong; a segmented
architecture does not violate the requirement that pointers to distinct
objects must not compare equal.
---
[ 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: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 24 Nov 2006 15:16:46 CST Raw View
"Krzysztof elechowski" wrote:
> The discussion below leads me to the following question: is it possible, in
> an actual implementation,
> that pointers to two unrelated objects actually compare equal where such a
> comparison introduces undefined behaviour?
> I suppose that the standard allows it; I would like to see a reference to an
> actual example (code, compiler vendor).
If there is undefined behavior, anything is possible. By
playing around with undefined behavior on an 8086 (in large
mode), for example, it was easy to get two pointers that
compared different but pointed to the same object. I don't have
any good example of the opposite, where pointers compared equal
but pointed to different objects, but I see no reason to believe
that it can't happen.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: tannhauser86549spam@free.fr (=?ISO-8859-15?Q?Falk_Tannh=E4user?=)
Date: Fri, 24 Nov 2006 23:33:23 GMT Raw View
Frederick Gotham schrieb:
> Give me two pointers of any type. If they are the addresses of different
> objects, then they must not be equal -- they must be unique:
Well, it depends what you mean by "different objects"...
> (Let's forget about inheritance for the moment.)
>
> template<class A,class B>
> bool PtrEquality(A const *const pa,B const *const pb)
> {
> return (void const volatile*)pa == (void const volatile*)pb;
> }
struct foo { int bar; long toto; short titi; };
int main()
{
union
{
int a;
double b;
};
foo f;
std::cout << std::boolalpha
<< PtrEquality(&a, &b) << ' '
<< PtrEquality(&f, &f.bar) << '\n';
return 0;
}
Falk
---
[ 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, 24 Nov 2006 23:33:42 GMT Raw View
Pete Becker:
> > This is forbidden by the C++ Standard. Every object must have a
> unique > address. E.g.:
>
> So, you seem to be claiming that it is impossible to guarantee that the
> addresses of different objects compare unequal on segmented
> architectures. That's simply wrong.
No, I'm not saying that. What I'm saying is that if you use operator== or
operator!= to compare pointers which point to different objects, then they
must NOT compare equal. Never. Never ever.
I know nothing about "segmented architectures" -- but if there's an
implementation out there which can give a false positive for comparing the
addresses of unrelated objects, then, my friend, you have a K++ compiler.
--
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: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 24 Nov 2006 17:34:10 CST Raw View
Francis Glassborow wrote:
> In article <4sm9u2F10ghauU1@mid.individual.net>, Bo Persson <bop@gmb.dk>
> writes
> >That's one reason for C++ to allow p==q to be different from
> >std::equal(p,q). The latter must normalize the pointers, if needed.
> I think the former must also. If p and q point to the same object the
> result of p==q is required to be true.
But only if there's no undefined behavior elsewhere. (Which is
also true for equal_to, of course.)
On most 8086 implementations, the compiler always generated the
same segment:offset pair for an address, and segments didn't
overlap. So basically p1 == p2 just compared the bit patterns
(the two 26 bit words) of the pointers. With a bit of undefined
behavior, however, it was fairly easy to obtain two pointers
with different bit patterns (and thus, which compared unequal)
which pointed to the same object.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 24 Nov 2006 17:36:33 CST Raw View
Pete Becker wrote:
> Frederick Gotham wrote:
> > "Bo Persson":
> >> It was all *very* common at the time the C++ standard was first drafted.
> >> Until Windows 95 came around, most of us used segmented memory, where
> >> pointers into different segments could not be compared without a lot of
> >> overhead. Different segmentation models, had their own specific problems.
> >> Here is one compiler that still supports this:
> >> http://www.digitalmars.com/ctg/ctgMemoryModel.html
> > This is forbidden by the C++ Standard. Every object must have a unique
> > address. E.g.:
> What, exactly, do you claim is forbidden? Segmented addressing is not a
> barrier to a conforming implementation of C++. There is no requirement
> that every object have a unique hardware address, just that every time
> you say &i for the same i you always get the same value.
Not even that is required, if by same value, you mean the same
representation. All that is required is that the values you get
compare equal (and that the compare unequal to all values for
pointers to other objects). And only then if your program has
no undefined behavior elsewhere.
It's been a very long time, but I think at least some 8086
compilers had an option to control this: you could get fast
pointer comparison which might be wrong if you had undefined
behavior elsewhere (undefined according to the C specification;
defined by the implemenation), or you could get a slower
comparison, which worked even in typical cases of undefined
behavior.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 24 Nov 2006 19:26:43 CST Raw View
Geo wrote:
> kuyper@wizard.net wrote:
> 'distinct representation' cannot mean 'unique address' otherwise it
> would not be possible to have conforming C++ on hardware with paged
> memory or in system which employ overlays !
Paged memory is generally handled transparently, and so causes
no problems. But you cannot have overlays in conformant C++.
Nor dynamically loaded objects, for that matter. But I'm not
sure that pointers are the problem. Two pointers to existing
objects must compare equal, but there's no guarantee concerning
pointers to objects which no longer exist. And presumable, if
you load a different overload, or a different dynamic object, in
place of an existing one, the objects in the original no longer
exist. The rules, if there were any, would presumably be the
same as when you delete an object.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 24 Nov 2006 19:26:17 CST Raw View
Krzysztof elechowski wrote:
> Under the assumption I can test whether arbitrary pointers are equal,
> I can test whether an arbitrary pointer lies in a given range
> because I can enumerate all cells in a range and test an arbitrary pointer
> against them.
Only if there were some type capable of holding that
enumeration. I've worked on at least one system where there
wasn't.
> It follows that, given a range of characters,
> it should be safe to take a shortcut
> and test whether a pointer lies within that range
> just by comparing it against the boundaries.
That could result in some very inefficient pointer comparisons.
At least if I understand what you are proposing. You want to
require pointers to map to some (possibly non-existing) integral
type, and do the comparisons on that.
> Suppose the test gives an incorrect result.
> It means that the pointer lies outside the range,
> because if it lay inside, the comparisons would be defined.
But how do you know that the test gave an incorrect result?
> It means that we get !(ptr < begin) && ptr < end.
> (I do not use the operator ">"
> because one could argue that you could have ptr < begin && ptr > begin).
> It follows
> that there exists such a pointer med within the range
> that !(ptr < med) && ptr != med && ptr < med + 1.
> How is this possible? I mean, implementation-wise?
I'm not too sure what you're arguing for. Typically, the
problem with comparing pointers comes up on machines on which
pointers don't map simply to integers. Machines with segmented
addressing, for example. On such machines, limiting comparisons
to addresses within a segment can greatly improve speed---on an
8086 in large model, for example p1 < p2 executed twice as fast
as p1 == p2.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: kuyper@wizard.net
Date: Sat, 25 Nov 2006 12:09:17 CST Raw View
Frederick Gotham wrote:
> Pete Becker:
>
> > > This is forbidden by the C++ Standard. Every object must have a
> > unique > address. E.g.:
> >
> > So, you seem to be claiming that it is impossible to guarantee that the
> > addresses of different objects compare unequal on segmented
> > architectures. That's simply wrong.
>
> No, I'm not saying that. What I'm saying is that if you use operator== or
> operator!= to compare pointers which point to different objects, then they
> must NOT compare equal. Never. Never ever.
That's not a problem that can occur in a segmented architecture.
> I know nothing about "segmented architectures" -- but if there's an
If you're not (incorrectly) claiming that this problem can come up in
segemented architectures, what precisely was the basis for your bald
assertion "This is forbidden by the C++ Standard"?
What was the antecedant of "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: "Bo Persson" <bop@gmb.dk>
Date: Sat, 25 Nov 2006 12:09:17 CST Raw View
Frederick Gotham wrote:
> Bo Persson:
>
>> It can be even worse, if we allow the segments to overlap (like in
>> x86 real mode). Then many combinations of segment:offset pairs may
>> infact point at the same location.
>>
>> That's one reason for C++ to allow p==q to be different from
>> std::equal(p,q). The latter must normalize the pointers, if needed.
>
>
> Did you mean to say "equal_to" instead of "equal"?
>
No, I meant std::less and operator<. :-)
20.5.7/8 says
"For templates greater, less, greater_equal, and less_equal, the
specializations for any pointer type yield a total order, even if the
built-in operators <, >, <=, >= do not."
Bo Persson
---
[ 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: "Kristof Zelechovski" <giecrilj@stegny.2a.pl>
Date: Sat, 25 Nov 2006 14:36:42 CST Raw View
Uzytkownik "James Kanze" <james.kanze@gmail.com> napisal w wiadomosci
news:1164402901.508861.172580@j44g2000cwa.googlegroups.com...
> "Krzysztof elechowski" wrote:
>> The discussion below leads me to the following question: is it possible,
>> in
>> an actual implementation,
>> that pointers to two unrelated objects actually compare equal where such
>> a
>> comparison introduces undefined behaviour?
>> I suppose that the standard allows it; I would like to see a reference to
>> an
>> actual example (code, compiler vendor).
>
> If there is undefined behavior, anything is possible. By
> playing around with undefined behavior on an 8086 (in large
> mode), for example, it was easy to get two pointers that
> compared different but pointed to the same object. I don't have
> any good example of the opposite, where pointers compared equal
> but pointed to different objects, but I see no reason to believe
> that it can't happen.
>
My assumption was the only source of undefined behaviour was the comparison
itself.
Chris
---
[ 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: "Kristof Zelechovski" <giecrilj@stegny.2a.pl>
Date: Sat, 25 Nov 2006 14:37:16 CST Raw View
I admit you sank my hypothesis, but what about using the following lifeboat:
Subtract the beginning of the range from the pointer to be examined.
The result may be random but it must be an integer.
(unless an exception is raised, in which case the method does not work).
Compare the difference to the length of the range.
If the difference is outside, the pointer is outside.
If the difference is inside,
the beginning of the range advanced by the difference points to a valid
cell.
Compare whether the address of that cell is equal to the pointer to be
examined.
Does it make a valid workaround?
How probable is it to raise an exception
by subtracting two unrelated pointers?
(I also understand that it would probably be a hardware exception that
cannot be caught.)
Chris
Uzytkownik "Hyman Rosen" <hyrosen@mail.com> napisal w wiadomosci
news:200611222116.kAMLG3Ux007675@horus.isnic.is...
Krzysztof elechowski wrote:
> It follows that, given a range of characters,
> it should be safe to take a shortcut
> and test whether a pointer lies within that range
> just by comparing it against the boundaries.
No, it does not follow at all. You are making unwarranted
assumptions about what the compiler does when you ask if
p1 == p2 and when you ask if p1 < p2. In fact, the reason
the standard (under)specifies this is because this was the
case on old x86 compilers. In the old days, there were
memory models under which a pointer was a 32-bit object
divided into two 16-bit pieces, a segment and an offset.
When you compared p1 == p2, the code generated a comparison
of the entire 32 bits, but when you compared p1 < p2 it
compared only the offsets, because objects were limited to
64K and pointers into the same object always had the same
segment part.
---
[ 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 ]
---
[ 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: bop@gmb.dk ("Bo Persson")
Date: Sat, 25 Nov 2006 20:35:33 GMT Raw View
Francis Glassborow wrote:
> In article <4sm9u2F10ghauU1@mid.individual.net>, Bo Persson
> <bop@gmb.dk> writes
>> That's one reason for C++ to allow p==q to be different from
>> std::equal(p,q). The latter must normalize the pointers, if needed.
>
> I think the former must also. If p and q point to the same object
> the result of p==q is required to be true.
Correct.
I should have written that the result of p<q can be different than
std::less(p,q). And of course only when p and q point to different objects.
Bo Persson
---
[ 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: giecrilj@stegny.2a.pl ("Kri tof elechovski")
Date: Sat, 25 Nov 2006 20:36:29 GMT Raw View
Uzytkownik ""Falk Tannh=E4user"" <tannhauser86549spam@free.fr> napisal w=20
wiadomosci news:456756aa$0$20532$426a74cc@news.free.fr...
> Frederick Gotham schrieb:
>> Give me two pointers of any type. If they are the addresses of differe=
nt=20
>> objects, then they must not be equal -- they must be unique:
>
> Well, it depends what you mean by "different objects"...
>
>> (Let's forget about inheritance for the moment.)
>>
>> template<class A,class B>
>> bool PtrEquality(A const *const pa,B const *const pb)
>> {
>> return (void const volatile*)pa =3D=3D (void const volatile*)pb;
>> }
>
> struct foo { int bar; long toto; short titi; };
>
> int main()
> {
> union
> {
> int a;
> double b;
> };
> foo f;
> std::cout << std::boolalpha
> << PtrEquality(&a, &b) << ' '
> << PtrEquality(&f, &f.bar) << '\n';
> return 0;
> }
>
> Falk
>
Interesting examples.
When you compare addresses of members of a union, at most one of them=20
exists;
you can assign a value to it to bring it to life.
In other words, one of the resulting pointers is write-only;
there is no object pointed to, it is merely a placeholder.
In the second case, the objects are related because one is a member of th=
e=20
other.
Therefore the principle under discussion
must be restricted to mereologically unrelated living objects.
Chris=20
---
[ 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: ron@spamcop.net (Ron Natalie)
Date: Sun, 26 Nov 2006 01:12:47 GMT Raw View
kuyper@wizard.net wrote:
>> No, I'm not saying that. What I'm saying is that if you use operator== or
>> operator!= to compare pointers which point to different objects, then they
>> must NOT compare equal. Never. Never ever.
>
> That's not a problem that can occur in a segmented architecture.
Umm, yes it is. If it is a problem which your architecture, you need
to make sure your compiler outputs appropriate code.
---
[ 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, 26 Nov 2006 01:17:03 GMT Raw View
Bo Persson:
> No, I meant std::less and operator<. :-)
>
> 20.5.7/8 says
> "For templates greater, less, greater_equal, and less_equal, the
> specializations for any pointer type yield a total order, even if the
> built-in operators <, >, <=, >= do not."
Now all we need to know is what a "total order" is.
--
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: giecrilj@stegny.2a.pl ("K i tof elechovski")
Date: Sun, 26 Nov 2006 01:17:40 GMT Raw View
U=BFytkownik "Frederick Gotham" <fgothamNO@SPAM.com> napisa=B3 w wiadomo=B6=
ci=20
news:6VC9h.16347$j7.334245@news.indigo.ie...
> Hyman Rosen:
>
>> In the old days, there were
>> memory models under which a pointer was a 32-bit object
>> divided into two 16-bit pieces, a segment and an offset.
>> When you compared p1 =3D=3D p2, the code generated a comparison
>> of the entire 32 bits, but when you compared p1 < p2 it
>> compared only the offsets, because objects were limited to
>> 64K and pointers into the same object always had the same
>> segment part.
>
>
> Magnificent example! Easily understood as follows:
>
> enum SegmentID { Seg1, Seg2, Seg3, Seg4 };
>
> struct Pointer {
> SegmentID seg;
> unsigned address;
> };
>
> bool Equal(Pointer const a,Pointer const b)
> {
> bool const seg_equality =3D a.seg=3D=3Db.seg;
> bool const address_equality =3D a.address=3D=3Db.address;
>
> return seg_equality && address_equality; /* Checks both of them */
> }
>
> bool Greater(Pointer const a,Pointer const b)
> {
> bool const address_equality =3D=3D b.address > a.address;
>
> return address_equality; /* Doesn't make sure of same segment! */
> }
>
That leads to a paradoxical conclusion that the loop
for(char const (*a_ptr)(*a_buf); a_ptr < a_buf[01]; ++a_ptr);
can be faster than the loop
for(char const (*a_ptr)(*a_buf); a_ptr !=3D a_buf[01]; ++a_ptr);
Usually the second loop is considered faster and the first one safer.
Chris=20
---
[ 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: giecrilj@stegny.2a.pl ("Kristof Zelechovski")
Date: Sun, 26 Nov 2006 01:16:43 GMT Raw View
Uzytkownik "James Kanze" <james.kanze@gmail.com> napisal w wiadomosci=20
news:1164405794.829286.192790@h54g2000cwb.googlegroups.com...
> Krzysztof =AFelechowski wrote:
>
>> Under the assumption I can test whether arbitrary pointers are equal,
>> I can test whether an arbitrary pointer lies in a given range
>> because I can enumerate all cells in a range and test an arbitrary=20
>> pointer
>> against them.
>
> Only if there were some type capable of holding that
> enumeration. I've worked on at least one system where there
> wasn't.
??
>> It follows that, given a range of characters,
>> it should be safe to take a shortcut
>> and test whether a pointer lies within that range
>> just by comparing it against the boundaries.
>
> That could result in some very inefficient pointer comparisons.
> At least if I understand what you are proposing. You want to
I was performing a thought experiment.
> require pointers to map to some (possibly non-existing) integral
> type, and do the comparisons on that.
>
I was investigating what I can get by following the rules of the standard.
I was not trying to require anything.
>> Suppose the test gives an incorrect result.
>> It means that the pointer lies outside the range,
>> because if it lay inside, the comparisons would be defined.
>
> But how do you know that the test gave an incorrect result?
By physical inspection, of course:
I open my computer case armed with a voltameter
and look at things as they really are :-)
We are in the environment of a thought experiment.
>
>> It means that we get !(ptr < begin) && ptr < end.
>> (I do not use the operator ">"
>> because one could argue that you could have ptr < begin && ptr > begin=
).
>> It follows
>> that there exists such a pointer med within the range
>> that !(ptr < med) && ptr !=3D med && ptr < med + 1.
>> How is this possible? I mean, implementation-wise?
>
> I'm not too sure what you're arguing for. Typically, the
> problem with comparing pointers comes up on machines on which
> pointers don't map simply to integers. Machines with segmented
> addressing, for example. On such machines, limiting comparisons
> to addresses within a segment can greatly improve speed---on an
> 8086 in large model, for example p1 < p2 executed twice as fast
> as p1 =3D=3D p2.
I was not arguing for anything. I just asked a question.
Chris
---
[ 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: Sat, 25 Nov 2006 20:45:26 CST Raw View
"K i tof elechovski":
> That leads to a paradoxical conclusion that the loop
> for(char const (*a_ptr)(*a_buf); a_ptr < a_buf[01]; ++a_ptr);
> can be faster than the loop
> for(char const (*a_ptr)(*a_buf); a_ptr != a_buf[01]; ++a_ptr);
> Usually the second loop is considered faster and the first one safer.
> Chris
Hmm... yes. Assuming that != is faster than <, (but not faster by more than
100%), the former would be faster on a segmented architecture, but the latter
would be faster on a non-segmented architecture. Interesting.
--
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: bop@gmb.dk ("Bo Persson")
Date: Sun, 26 Nov 2006 18:23:42 GMT Raw View
Frederick Gotham wrote:
> Bo Persson:
>
>> No, I meant std::less and operator<. :-)
>>
>> 20.5.7/8 says
>> "For templates greater, less, greater_equal, and less_equal, the
>> specializations for any pointer type yield a total order, even if
>> the built-in operators <, >, <=, >= do not."
>
>
> Now all we need to know is what a "total order" is.
It is an ordering that is stronger than weak and partial ordering. :-)
Section 25.3/4 says so.
Unfortunately, what could have been a definition of strict ordering is just
a note. So formally perhaps we don't know.
Bo Persson
---
[ 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: "James Kanze" <james.kanze@gmail.com>
Date: Sun, 26 Nov 2006 12:24:30 CST Raw View
Frederick Gotham wrote:
> Pete Becker:
> > > This is forbidden by the C++ Standard. Every object must have a
> > > unique address. E.g.:
> > So, you seem to be claiming that it is impossible to guarantee that the
> > addresses of different objects compare unequal on segmented
> > architectures. That's simply wrong.
> No, I'm not saying that. What I'm saying is that if you use operator== or
> operator!= to compare pointers which point to different objects, then they
> must NOT compare equal. Never. Never ever.
In a legal C++ program. If the program has undefined behavior
elsewhere, all bets are off.
And you have to be careful about how you understand "point to
different objects":
int a ;
int b[ 1 ] ;
assert( &a != b + 1 ) ;
is not guaranteed. But only because b+1 doesn't point to an
object. A pointer to one past the end of an array may point to
another object as well.
> I know nothing about "segmented architectures" -- but if
> there's an implementation out there which can give a false
> positive for comparing the addresses of unrelated objects,
> then, my friend, you have a K++ compiler.
It depends. If this occurs in a 100% conformant program, with
no undefined behavior, true (although see the problem with
pointers one past the end). If the program has even the
slightest undefined behavior (accessing a union other than
through the last member written, accessing through a pointer
resulting from a reinterpret_cast, incrementing beyond the end
of an array, etc.), then all bets are off. For that matter, on
an 8086, given:
int scalar ;
int array[ 8 ] ;
int* ps = &s ;
int* pa = array + 8 ;
pa could actually point to scalar, but not compare equal to ps.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: "James Kanze" <james.kanze@gmail.com>
Date: Sun, 26 Nov 2006 17:58:16 CST Raw View
"K i tof elechovski" wrote:
> U ytkownik "Frederick Gotham" <fgothamNO@SPAM.com> napisa w wiadomo ci
> news:6VC9h.16347$j7.334245@news.indigo.ie...
> > Hyman Rosen:
> >> In the old days, there were
> >> memory models under which a pointer was a 32-bit object
> >> divided into two 16-bit pieces, a segment and an offset.
> >> When you compared p1 == p2, the code generated a comparison
> >> of the entire 32 bits, but when you compared p1 < p2 it
> >> compared only the offsets, because objects were limited to
> >> 64K and pointers into the same object always had the same
> >> segment part.
> > Magnificent example! Easily understood as follows:
> > enum SegmentID { Seg1, Seg2, Seg3, Seg4 };
> > struct Pointer {
> > SegmentID seg;
> > unsigned address;
> > };
> > bool Equal(Pointer const a,Pointer const b)
> > {
> > bool const seg_equality = a.seg==b.seg;
> > bool const address_equality = a.address==b.address;
> > return seg_equality && address_equality; /* Checks both of them */
> > }
> > bool Greater(Pointer const a,Pointer const b)
> > {
> > bool const address_equality == b.address > a.address;
> > return address_equality; /* Doesn't make sure of same segment! */
> > }
> That leads to a paradoxical conclusion that the loop
> for(char const (*a_ptr)(*a_buf); a_ptr < a_buf[01]; ++a_ptr);
> can be faster than the loop
> for(char const (*a_ptr)(*a_buf); a_ptr != a_buf[01]; ++a_ptr);
> Usually the second loop is considered faster and the first one safer.
By whom? I've never encountered an architecture where the
second was faster; on most architectures, they're the same; on
segmented architectures, the first is potentially faster, at
least.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
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: krixel@qed.pl ("Krzysztof elechowski")
Date: Wed, 22 Nov 2006 16:41:33 GMT Raw View
The discussion below leads me to the following question: is it possible, =
in=20
an actual implementation,
that pointers to two unrelated objects actually compare equal where such =
a=20
comparison introduces undefined behaviour?
I suppose that the standard allows it; I would like to see a reference to=
an=20
actual example (code, compiler vendor).
Chris
U=BFytkownik ""Bo Persson"" <bop@gmb.dk> napisa=B3 w wiadomo=B6ci=20
news:4seemkFv5d43U1@mid.individual.net...
"Alf P. Steinbach" wrote:
> * Frederick Gotham:
>> As well as the intrinsic types in C++ (e.g. int, short, bool,
>> float), the C++ Standard provides other special types for specific
>> purposes. A prime example would be "size_t", which is appropriate
>> for storing: (1) The size of an object.
>> (2) The amount of elements in an array.
>> (3) The length of a string.
>>
>> This is the purpose of size_t, and we expect size_t to fulfill its
>> duties adequately. In particular, we needn't worry about whether
>> the appropriate values are too big to store in a size_t.
>>
>> Given that particular special types are provided by the Standard
>> Library, one would assume that these types are appropriate for
>> their intended purpose... but it seems to me that one of them is
>> inherently inadequate: ptrdiff_t.
>>
>> What's the purpose of ptrdiff_t? Well, we should able to use
>> ptrdiff_t to store the address of subtracting two memory addresses
>> (provided that both addresses point to parts of the same object).
>> However, it seems that the C++ Standard explicitly says that
>> ptrdiff_t is inadequate for this task. Here's the relevant passage:
>>
>> 5.7.6
>> 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. The type of the result is an
>> implementation-defined signed integral type; this type shall be
>> the same type that is defined as ptrdiff_t in the <cstddef> header
>> (18.1). As with any other arithmetic overflow, if the result does
>> not fit in the space provided, the behavior is undefined. In other
>> words, if the expressions P and Q point to, respectively, the i-th
>> and j-th elements of an array object, the expression (P)-(Q) has
>> the value i=96j provided the value fits in an object of type
>> ptrdiff_t. What use is this? By my own understanding, it's basically=20
>> telling
>> us in plain English that ptrdiff_t isn't up for the job.
>
> Yes. ptrdiff_t is signed. In practice it may be that it's too
> costly, in some sense, to make sizeof(ptrdiff_t) larger than
> sizeof(size_t); hence ptrdiff_t has at most half the positive range
> of size_t, and hence, for an array of char that fills over half of
> memory, you may get into trouble using simple raw pointer
> subtraction -- so don't. ;-)
Luckily, some of the most popular operating systems will save you here, b=
y
reserving one half of the address space for itself. And fragment the rest.
:-)
>
> I agree that the standard could and should be /explicit/ about that
> and not use weasel formulations.
That would be more like a tutorial, and not an open standard. It is prett=
y
vague on memory organization as a whole, to allow as many alternatives as
possible. Especially segmented memory models, that were very "popular" at
the time the standard was first drafted.
With segments, the phrase "elements of the same object" saves you, as
objects will be limited to the segment size.
Right now we live in the strangest of times, when virtual and physical
memory is about the same size. That will go away soon (around jan 30th, o=
r
so :-).
Bo Persson
---
[ 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 ]
---
[ 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, 22 Nov 2006 18:42:50 GMT Raw View
"Krzysztof =AFelechowski":
> The discussion below leads me to the following question: is it possible=
,
> in an actual implementation,
> that pointers to two unrelated objects actually compare equal where suc=
h
> a comparison introduces undefined behaviour?
No, but not for the reason you think. Here are two unrelated objects:
T a,b;
There's nothing wrong with doing:
a =3D=3D b a !=3D b
But the behaviour is undefined if you do:
a < b a > b a <=3D b a >=3D b
I can't think of any circumstances in which you're not allowed check if=20
pointers are equal/unequal. However, there's places where you can't check=
if=20
they're greater or less (such as the example shown above).
--=20
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: bop@gmb.dk ("Bo Persson")
Date: Wed, 22 Nov 2006 19:59:26 GMT Raw View
"Krzysztof =AFelechowski" wrote:
> The discussion below leads me to the following question: is it
> possible, in an actual implementation,
> that pointers to two unrelated objects actually compare equal where
> such a comparison introduces undefined behaviour?
> I suppose that the standard allows it; I would like to see a
> reference to an actual example (code, compiler vendor).
> Chris
It was all *very* common at the time the C++ standard was first drafted.=20
Until Windows 95 came around, most of us used segmented memory, where=20
pointers into different segments could not be compared without a lot of=20
overhead. Different segmentation models, had their own specific problems.
Here is one compiler that still supports this:
http://www.digitalmars.com/ctg/ctgMemoryModel.html
Bo Persson
>
> U=BFytkownik ""Bo Persson"" <bop@gmb.dk> napisa=B3 w wiadomo=B6ci
>
> That would be more like a tutorial, and not an open standard. It is
> pretty vague on memory organization as a whole, to allow as many
> alternatives as possible. Especially segmented memory models, that
> were very "popular" at the time the standard was first drafted.
>
> With segments, the phrase "elements of the same object" saves you,
> as objects will be limited to the segment size.
>
> Right now we live in the strangest of times, when virtual and
> physical memory is about the same size. That will go away soon
> (around jan 30th, or so :-).
>
---
[ 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: "Krzysztof elechowski" <krixel@qed.pl>
Date: Wed, 22 Nov 2006 14:18:28 CST Raw View
Attn. Mod:
My Outlook Express 6 fails to insert quotation marks properly in some cases
when I reply.
And there is no way to insert them afterwards.
Under the assumption I can test whether arbitrary pointers are equal,
I can test whether an arbitrary pointer lies in a given range
because I can enumerate all cells in a range and test an arbitrary pointer
against them.
It follows that, given a range of characters,
it should be safe to take a shortcut
and test whether a pointer lies within that range
just by comparing it against the boundaries.
Suppose the test gives an incorrect result.
It means that the pointer lies outside the range,
because if it lay inside, the comparisons would be defined.
It means that we get !(ptr < begin) && ptr < end.
(I do not use the operator ">"
because one could argue that you could have ptr < begin && ptr > begin).
It follows
that there exists such a pointer med within the range
that !(ptr < med) && ptr != med && ptr < med + 1.
How is this possible? I mean, implementation-wise?
Chris
U ytkownik "Frederick Gotham" <fgothamNO@SPAM.com> napisa w wiadomo ci
news:Jf%8h.16288$j7.333930@news.indigo.ie...
"Krzysztof elechowski":
> The discussion below leads me to the following question: is it possible,
> in an actual implementation,
> that pointers to two unrelated objects actually compare equal where such
> a comparison introduces undefined behaviour?
No, but not for the reason you think. Here are two unrelated objects:
T a,b;
There's nothing wrong with doing:
a == b a != b
But the behaviour is undefined if you do:
a < b a > b a <= b a >= b
I can't think of any circumstances in which you're not allowed check if
pointers are equal/unequal. However, there's places where you can't check if
they're greater or less (such as the example shown above).
--
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 ]
---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 22 Nov 2006 21:42:00 GMT Raw View
Krzysztof =AFelechowski wrote:
> It follows that, given a range of characters,
> it should be safe to take a shortcut
> and test whether a pointer lies within that range
> just by comparing it against the boundaries.
No, it does not follow at all. You are making unwarranted
assumptions about what the compiler does when you ask if
p1 =3D=3D p2 and when you ask if p1 < p2. In fact, the reason
the standard (under)specifies this is because this was the
case on old x86 compilers. In the old days, there were
memory models under which a pointer was a 32-bit object
divided into two 16-bit pieces, a segment and an offset.
When you compared p1 =3D=3D p2, the code generated a comparison
of the entire 32 bits, but when you compared p1 < p2 it
compared only the offsets, because objects were limited to
64K and pointers into the same object always had the same
segment part.
---
[ 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, 22 Nov 2006 21:44:12 GMT Raw View
"Bo Persson":
> It was all *very* common at the time the C++ standard was first drafted.
> Until Windows 95 came around, most of us used segmented memory, where
> pointers into different segments could not be compared without a lot of
> overhead. Different segmentation models, had their own specific problems.
>
> Here is one compiler that still supports this:
>
> http://www.digitalmars.com/ctg/ctgMemoryModel.html
This is forbidden by the C++ Standard. Every object must have a unique
address. E.g.:
int i;
int &Func1()
{
static int a;
return a;
}
int &Func2()
{
return *new int;
}
#include <ostream>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int *p = &i, *q = &Func1(), *r = &Func2();
if ( p==q || q==r || p==r )
cout << "This is a K++ compiler." << endl;
}
--
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: kst-u@mib.org (Keith Thompson)
Date: Wed, 22 Nov 2006 22:50:39 GMT Raw View
fgothamNO@SPAM.com (Frederick Gotham) writes:
> "Krzysztof =AFelechowski":
>> The discussion below leads me to the following question: is it possibl=
e,
>> in an actual implementation,
>> that pointers to two unrelated objects actually compare equal where su=
ch
>> a comparison introduces undefined behaviour?
>
> No, but not for the reason you think. Here are two unrelated objects:
>
> T a,b;
>
> There's nothing wrong with doing:
>
> a =3D=3D b a !=3D b
Right.
> But the behaviour is undefined if you do:
>
> a < b a > b a <=3D b a >=3D b
Right.
> I can't think of any circumstances in which you're not allowed check if=
=20
> pointers are equal/unequal. However, there's places where you can't che=
ck if=20
> they're greater or less (such as the example shown above).
If an operand has an indeterminate value, then just evaluating the
operand invokes undefined behavior. Barring that, "=3D" and "!=3D" shoul=
d
be well-defined in all cases.
But for cases where "<", ">", "<=3D", and ">=3D" invoke undefined
behavior, they can behave in a manner that's consistent with the
operands being equal even if they're not. For example, we might have
the following:
a < b (no)
a > b (no)
a <=3D b (yes)
a >=3D b (yes)
a =3D=3D b (no)
a !=3D b (yes)
This could plausibly happen in, say, a segmented architecture, where
an address consists of a segment number and an offset within the
segment. "=3D=3D" and "!=3D" would have to compare both components of ea=
ch
address. "<" et al can *assume* that both operands point within the
same object, and therefore that they're in the same segment. Thus two
pointers with different segment numbers but (coincidentally) identical
offsets would appear to be unequal using "=3D=3D" and "!=3D", but (falsel=
y)
equal using "<=3D" and ">=3D".
--=20
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~ks=
t>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~k=
st>
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: kuyper@wizard.net
Date: Wed, 22 Nov 2006 16:54:57 CST Raw View
Krzysztof elechowski wrote:
..
> Under the assumption I can test whether arbitrary pointers are equal,
Almost. You can test arbitrary VALID pointers for equality. Using an
uninitialized pointer, or a pointer whose last-stored value pointed
into memory that is no longer allocated, does not have defined
behavior.
> I can test whether an arbitrary pointer lies in a given range
> because I can enumerate all cells in a range and test an arbitrary pointer
> against them.
> It follows that, given a range of characters,
> it should be safe to take a shortcut
> and test whether a pointer lies within that range
> just by comparing it against the boundaries.
That conclusion does not follow from the argument you've given. As a
separate matter, it also happens to not be true. Comparisons of
pointers for order have results specified by the standard only if they
both point within or one past the end of the same object. It is both
possible, and a feature of real systems, that such comparisons can
produce results that render your "shortcut" useless.
> Suppose the test gives an incorrect result.
> It means that the pointer lies outside the range,
> because if it lay inside, the comparisons would be defined.
Such a test can give a correct result indicating that the pointer is
outside the range, a correct result indicating that the pointer is
inside the range, or an incorrect result indicating that the pointer is
inside the range.
The one thing it is not permitted to do is give an incorrect result
indicating that the pointer is outside the range. That's because, if
such a result would be incorrect, then the behavior is defined, and the
defined behavior is to give the correct answer.
> It means that we get !(ptr < begin) && ptr < end
Unless there is a single object that ptr and begin both point either
into or one past the end of, the result of ptr<begin is unspecified.
Unless there is a single object that ptr and end both point either into
or one past the end of, the result of ptr<begin is unspecified. When
neither comparison has a specified result, that expression can be
either true or false; a fact that seriously impairs its usefulness. :-)
---
[ 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: pete@versatilecoding.com (Pete Becker)
Date: Wed, 22 Nov 2006 23:00:49 GMT Raw View
Frederick Gotham wrote:
> "Bo Persson":
>
>> It was all *very* common at the time the C++ standard was first drafted.
>> Until Windows 95 came around, most of us used segmented memory, where
>> pointers into different segments could not be compared without a lot of
>> overhead. Different segmentation models, had their own specific problems.
>>
>> Here is one compiler that still supports this:
>>
>> http://www.digitalmars.com/ctg/ctgMemoryModel.html
>
>
> This is forbidden by the C++ Standard. Every object must have a unique
> address. E.g.:
>
What, exactly, do you claim is forbidden? Segmented addressing is not a
barrier to a conforming implementation of C++. There is no requirement
that every object have a unique hardware address, just that every time
you say &i for the same i you always get the same value.
--
-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
---
[ 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: alfps@start.no ("Alf P. Steinbach")
Date: Wed, 22 Nov 2006 23:20:42 GMT Raw View
* kuyper@wizard.net:
>
> Comparisons of
> pointers for order have results specified by the standard only if they
> both point within or one past the end of the same object.
You probably mean, comparision using the built-in operators.
Otherwise we'd have a hard time placing pointers in collections.
Happily there's std::less & family. ;-)
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ 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, 22 Nov 2006 22:20:42 CST Raw View
Pete Becker wrote:
> Frederick Gotham wrote:
> > "Bo Persson":
> >
> >> It was all *very* common at the time the C++ standard was first drafted.
> >> Until Windows 95 came around, most of us used segmented memory, where
> >> pointers into different segments could not be compared without a lot of
> >> overhead. Different segmentation models, had their own specific problems.
> >>
> >> Here is one compiler that still supports this:
> >>
> >> http://www.digitalmars.com/ctg/ctgMemoryModel.html
> >
> >
> > This is forbidden by the C++ Standard. Every object must have a unique
> > address. E.g.:
> >
>
> What, exactly, do you claim is forbidden? Segmented addressing is not a
> barrier to a conforming implementation of C++. There is no requirement
> that every object have a unique hardware address, just that every time
> you say &i for the same i you always get the same value.
There's a few more requirement than just that one; two pointers must
compare equal if and only if they point to the same object. That's
pretty difficult to do unless pointers to distinct objects have
distinct representations.
---
[ 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: pete@versatilecoding.com (Pete Becker)
Date: Thu, 23 Nov 2006 18:49:15 GMT Raw View
kuyper@wizard.net wrote:
> Pete Becker wrote:
>> Frederick Gotham wrote:
>>> "Bo Persson":
>>>
>>>> It was all *very* common at the time the C++ standard was first drafted.
>>>> Until Windows 95 came around, most of us used segmented memory, where
>>>> pointers into different segments could not be compared without a lot of
>>>> overhead. Different segmentation models, had their own specific problems.
>>>>
>>>> Here is one compiler that still supports this:
>>>>
>>>> http://www.digitalmars.com/ctg/ctgMemoryModel.html
>>>
>>> This is forbidden by the C++ Standard. Every object must have a unique
>>> address. E.g.:
>>>
>> What, exactly, do you claim is forbidden? Segmented addressing is not a
>> barrier to a conforming implementation of C++. There is no requirement
>> that every object have a unique hardware address, just that every time
>> you say &i for the same i you always get the same value.
>
> There's a few more requirement than just that one; two pointers must
> compare equal if and only if they point to the same object. That's
> pretty difficult to do unless pointers to distinct objects have
> distinct representations.
>
But, again, that has nothing to do with whether the hardware allows
multiple representations of the same address.
I'm really not interested in discussing how to implement compilers for
segmented address architectures. It's not that hard. What I'm wondering
is what the original claim actually means. On its surface, it seems to
be saying that it is impossible to implement a conforming C++ compiler
on a segmented architecture. That's simply false.
--
-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
---
[ 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: "Geo" <gg@remm.org>
Date: Thu, 23 Nov 2006 13:04:05 CST Raw View
kuyper@wizard.net wrote:
> Pete Becker wrote:
> > Frederick Gotham wrote:
> > > "Bo Persson":
> > >
> > >> It was all *very* common at the time the C++ standard was first drafted.
> > >> Until Windows 95 came around, most of us used segmented memory, where
> > >> pointers into different segments could not be compared without a lot of
> > >> overhead. Different segmentation models, had their own specific problems.
> > >>
> > >> Here is one compiler that still supports this:
> > >>
> > >> http://www.digitalmars.com/ctg/ctgMemoryModel.html
> > >
> > >
> > > This is forbidden by the C++ Standard. Every object must have a unique
> > > address. E.g.:
> > >
> >
> > What, exactly, do you claim is forbidden? Segmented addressing is not a
> > barrier to a conforming implementation of C++. There is no requirement
> > that every object have a unique hardware address, just that every time
> > you say &i for the same i you always get the same value.
>
> There's a few more requirement than just that one; two pointers must
> compare equal if and only if they point to the same object. That's
> pretty difficult to do unless pointers to distinct objects have
> distinct representations.
>
No, you've lost me now, still don't see what's forbidden?
'distinct representation' cannot mean 'unique address' otherwise it
would not be possible to have conforming C++ on hardware with paged
memory or in system which employ overlays !
---
[ 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: "Bo Persson" <bop@gmb.dk>
Date: Fri, 24 Nov 2006 00:16:08 CST Raw View
Keith Thompson wrote:
> This could plausibly happen in, say, a segmented architecture, where
> an address consists of a segment number and an offset within the
> segment. "==" and "!=" would have to compare both components of
> each address. "<" et al can *assume* that both operands point
> within the same object, and therefore that they're in the same
> segment. Thus two pointers with different segment numbers but
> (coincidentally) identical offsets would appear to be unequal using
> "==" and "!=", but (falsely) equal using "<=" and ">=".
It can be even worse, if we allow the segments to overlap (like in x86 real
mode). Then many combinations of segment:offset pairs may infact point at
the same location.
That's one reason for C++ to allow p==q to be different from
std::equal(p,q). The latter must normalize the pointers, if needed.
Bo Persson
---
[ 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: Mon, 20 Nov 2006 12:05:13 CST Raw View
As well as the intrinsic types in C++ (e.g. int, short, bool, float), the
C++ Standard provides other special types for specific purposes. A prime
example would be "size_t", which is appropriate for storing:
(1) The size of an object.
(2) The amount of elements in an array.
(3) The length of a string.
This is the purpose of size_t, and we expect size_t to fulfill its duties
adequately. In particular, we needn't worry about whether the appropriate
values are too big to store in a size_t.
Given that particular special types are provided by the Standard Library,
one would assume that these types are appropriate for their intended
purpose... but it seems to me that one of them is inherently inadequate:
ptrdiff_t.
What's the purpose of ptrdiff_t? Well, we should able to use ptrdiff_t to
store the address of subtracting two memory addresses (provided that both
addresses point to parts of the same object). However, it seems that the
C++ Standard explicitly says that ptrdiff_t is inadequate for this task.
Here's the relevant passage:
5.7.6
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. The
type of the result is an implementation-defined signed integral type; this
type shall be the same type that is defined as ptrdiff_t in the <cstddef>
header (18.1). As with any other arithmetic overflow, if the result does
not fit in the space provided, the behavior is undefined. In other words,
if the expressions P and Q point to, respectively, the i-th and j-th
elements of an array object, the expression (P)-(Q) has the value i j
provided the value fits in an object of type ptrdiff_t.
What use is this? By my own understanding, it's basically telling us in
plain English that ptrdiff_t isn't up for the job. Here's some sample code:
size_t const len = 4096;
char unsigned *const p = new char unsigned[len];
char unsigned const *const pover = p + len;
size_t const x = pover - len;
Looking at that last line immediately above, it seems that the Standard
doesn't give us any guarantee at all that it will work. Is it just me, or
is there something wrong here? Why provide ptrdiff_t at all if it can't do
its job?
--
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: "Alf P. Steinbach" <alfps@start.no>
Date: Mon, 20 Nov 2006 12:35:35 CST Raw View
* Frederick Gotham:
> As well as the intrinsic types in C++ (e.g. int, short, bool, float), the
> C++ Standard provides other special types for specific purposes. A prime
> example would be "size_t", which is appropriate for storing:
>
> (1) The size of an object.
> (2) The amount of elements in an array.
> (3) The length of a string.
>
> This is the purpose of size_t, and we expect size_t to fulfill its duties
> adequately. In particular, we needn't worry about whether the appropriate
> values are too big to store in a size_t.
>
> Given that particular special types are provided by the Standard Library,
> one would assume that these types are appropriate for their intended
> purpose... but it seems to me that one of them is inherently inadequate:
> ptrdiff_t.
>
> What's the purpose of ptrdiff_t? Well, we should able to use ptrdiff_t to
> store the address of subtracting two memory addresses (provided that both
> addresses point to parts of the same object). However, it seems that the
> C++ Standard explicitly says that ptrdiff_t is inadequate for this task.
> Here's the relevant passage:
>
> 5.7.6
> 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. The
> type of the result is an implementation-defined signed integral type; this
> type shall be the same type that is defined as ptrdiff_t in the <cstddef>
> header (18.1). As with any other arithmetic overflow, if the result does
> not fit in the space provided, the behavior is undefined. In other words,
> if the expressions P and Q point to, respectively, the i-th and j-th
> elements of an array object, the expression (P)-(Q) has the value i j
> provided the value fits in an object of type ptrdiff_t.
>
> What use is this? By my own understanding, it's basically telling us in
> plain English that ptrdiff_t isn't up for the job.
Yes. ptrdiff_t is signed. In practice it may be that it's too costly,
in some sense, to make sizeof(ptrdiff_t) larger than sizeof(size_t);
hence ptrdiff_t has at most half the positive range of size_t, and
hence, for an array of char that fills over half of memory, you may get
into trouble using simple raw pointer subtraction -- so don't. ;-)
I agree that the standard could and should be /explicit/ about that and
not use weasel formulations.
But that's the backseat driver talking.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ 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: Ron Natalie <ron@spamcop.net>
Date: Mon, 20 Nov 2006 14:29:53 CST Raw View
Frederick Gotham wrote:
>
> What use is this? By my own understanding, it's basically telling us in
> plain English that ptrdiff_t isn't up for the job. Here's some sample code:
>
> size_t const len = 4096;
>
> char unsigned *const p = new char unsigned[len];
> char unsigned const *const pover = p + len;
>
> size_t const x = pover - len;
>
> Looking at that last line immediately above, it seems that the Standard
> doesn't give us any guarantee at all that it will work. Is it just me, or
> is there something wrong here? Why provide ptrdiff_t at all if it can't do
> its job?
>
size_t is UNSIGNED.
ptrdiff_t is SIGNED.
The issue is that if you have a sufficiently large object it's size
could be representable by size_t, but have relative offsets that
would be too big to represent in ptrdiff_t.
For example, lets say you do:
char foo[2147483650];
on a machine where the maximum integer is 32 bits long.
size_t could represent sizeof foo.
ptrdiff_t could represent &foo[1] - &foo[0] but not
&foo[2147483649] - &foo[0].
---
[ 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: bop@gmb.dk ("Bo Persson")
Date: Mon, 20 Nov 2006 20:33:24 GMT Raw View
"Alf P. Steinbach" wrote:
> * Frederick Gotham:
>> As well as the intrinsic types in C++ (e.g. int, short, bool,
>> float), the C++ Standard provides other special types for specific
>> purposes. A prime example would be "size_t", which is appropriate
>> for storing: (1) The size of an object.
>> (2) The amount of elements in an array.
>> (3) The length of a string.
>>
>> This is the purpose of size_t, and we expect size_t to fulfill its
>> duties adequately. In particular, we needn't worry about whether
>> the appropriate values are too big to store in a size_t.
>>
>> Given that particular special types are provided by the Standard
>> Library, one would assume that these types are appropriate for
>> their intended purpose... but it seems to me that one of them is
>> inherently inadequate: ptrdiff_t.
>>
>> What's the purpose of ptrdiff_t? Well, we should able to use
>> ptrdiff_t to store the address of subtracting two memory addresses
>> (provided that both addresses point to parts of the same object).
>> However, it seems that the C++ Standard explicitly says that
>> ptrdiff_t is inadequate for this task. Here's the relevant passage:
>>
>> 5.7.6
>> 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. The type of the result is an
>> implementation-defined signed integral type; this type shall be
>> the same type that is defined as ptrdiff_t in the <cstddef> header
>> (18.1). As with any other arithmetic overflow, if the result does
>> not fit in the space provided, the behavior is undefined. In other
>> words, if the expressions P and Q point to, respectively, the i-th
>> and j-th elements of an array object, the expression (P)-(Q) has
>> the value i=96j provided the value fits in an object of type
>> ptrdiff_t. What use is this? By my own understanding, it's basically=20
>> telling
>> us in plain English that ptrdiff_t isn't up for the job.
>
> Yes. ptrdiff_t is signed. In practice it may be that it's too
> costly, in some sense, to make sizeof(ptrdiff_t) larger than
> sizeof(size_t); hence ptrdiff_t has at most half the positive range
> of size_t, and hence, for an array of char that fills over half of
> memory, you may get into trouble using simple raw pointer
> subtraction -- so don't. ;-)
Luckily, some of the most popular operating systems will save you here, b=
y=20
reserving one half of the address space for itself. And fragment the rest=
.=20
:-)
>
> I agree that the standard could and should be /explicit/ about that
> and not use weasel formulations.
That would be more like a tutorial, and not an open standard. It is prett=
y=20
vague on memory organization as a whole, to allow as many alternatives as=
=20
possible. Especially segmented memory models, that were very "popular" at=
=20
the time the standard was first drafted.
With segments, the phrase "elements of the same object" saves you, as=20
objects will be limited to the segment size.
Right now we live in the strangest of times, when virtual and physical=20
memory is about the same size. That will go away soon (around jan 30th, o=
r=20
so :-).
Bo Persson
---
[ 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: Mon, 20 Nov 2006 23:53:23 GMT Raw View
Frederick Gotham <fgothamNO@SPAM.com> writes:
[...]
> What's the purpose of ptrdiff_t? Well, we should able to use ptrdiff_t to
> store the address of subtracting two memory addresses (provided that both
> addresses point to parts of the same object). However, it seems that the
> C++ Standard explicitly says that ptrdiff_t is inadequate for this task.
> Here's the relevant passage:
[snip]
(Quibble: It's the *result* of subtracting two addresses; that result
is not itself an address. I'm sure you know that.)
We should be able to use int to store the result of subtracting two
ints. However since the result of such a subtraction can be outside
the range of int, it's clear that int is inadequate for this task.
One solution would have been to define the "-" operator to yield a
result of a type wide enough to hold any possible result -- but then
we wouldn't be able to subtract values of the widest signed integer
type.
In the case of ptrdiff_t, an implementation is allowed, but not
required, to make it bigger than size_t, so it actually can store any
possible result without overflow. (I don't know of any
implementations that actually do this.)
These days, on 32-bit systems (by which I mean systems where size_t,
and presumably pointers, are 32 bits), overflow is a real possibility
*if* the implementation allows objects to be larger than 2 gigabytes.
On 64-bit systems, presumably size_t, pointers, and ptrdiff_t are all
64 bits, and there's no real possibility of overlow unless the
implementation supports objects bigger than 8 exabytes. In historical
context, ptrdiff_t overflow is an issue only when systems are just
approaching the limits of their current pointer sizes; the problem is
alleviated when pointers get bigger and the addressing space grows by
some huge factor.
--
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 ]