I
In a little while
thanks
In a little while said:thanks
In said:thanks
John said:Cast each of them to an integer type and perform the subtraction.
To cover ever possible address value, you will need a pointer-sized integer
type and it will need to be unsigned.
std:trdiff_t
Since it is unsigned, you can only subtract the smaller from the larger, so
you will need to do an if() test to establish which is smaller before doing
the subtraction.
Gianni Mariani said:what would you use that for ?
who said it is unsigned ?
Frederick Gotham said:To calcualte the amount of bytes between two addresses:
#include <cstddef>
#include <cassert>
template<class A,class B>
std:trdiff_t BytesBetween(A const *const pa,B const *const pb)
{
assert(pa); assert(pb);
return pb - pa;
}
Of course, anyone worth half shiling would simply write:
(char const*)pa - (char const*)pb;
This behaviour of this code is undefined if the pointers do not point
to bytes, members or elements of the same object.
Someone else suggested casting to integer types -- the behaviour of
this is undefined by the C++ Standard (or at the most, implementation
defined).
This doesn't give a byte measure. Further, it won't compile if A and B
are different types.
Someone else suggested casting to integer types -- the behaviour of
this is undefined by the C++ Standard (or at the most, implementation
defined).
It is certainly not undefined. Section 5.2.10/4 reads as follows:
"A pointer can be explicitly converted to any integral type large enough
to hold it. The mapping function is implementation-defined [Note: it is
intended to be unsurprising to those who know the addressing structure
of the underlying machine. ]"
This refers to a reinterpret_cast. By 5.4/5, a reinterpret_cast can be
performed using C-style cast notation.
Frederick Gotham said:John Carson:
It is certainly not undefined. Section 5.2.10/4 reads as follows:
"A pointer can be explicitly converted to any integral type large
enough to hold it. The mapping function is implementation-defined
[Note: it is intended to be unsurprising to those who know the
addressing structure of the underlying machine. ]"
This refers to a reinterpret_cast. By 5.4/5, a reinterpret_cast can
be performed using C-style cast notation.
1: Why would you cast to integer type when you can simply subtract
pointers?
2: The C++ Standard doesn't necessitate the existance of an integer
type which can hold a byte address accurately.
3: Even if such an integer type exists, the behaviour of performing
arithmetic upon the integer value and then casting back to a pointer
type is not defined by the C++ Standard.
You can't "simply subtract pointers" and get a byte measure without a
cast (unless you have char* pointers to begin with),
Correct.
so the advantage of
pointers is not obvious.
Using integers is more natural when you are
doing integer arithmetic (as opposed to pointer arithmetic) on
addresses.
It also doesn't guarantee that std:trdiff_t or any other type can hold
(char const volatile*)pb - (char const volatile*)pa;
See Section 5.7/6.
On many platforms (Windows, in particular) there is a type that will
hold a byte address accurately. Indeed, Windows provides an integer type
called UINT_PTR which is specifically for this purpose.
Nor is it defined if you work with a char* pointer.
Frederick Gotham said:John Carson:
It's obvious to me... but then again I know what I'm doing.
What planet are you on? I hope you don't work professionally as a C++
programmer, do you?
Here's some code that will work perfectly:
struct MyPOD {
int a;
char b;
void *c;
double d;
} obj;
ptrdiff_t distance_a_to_d = (char*)&obj.d - (char*)&obj.a;
I'll give you the benefit of the doubt and pretend that the address
of a byte can be accurately stored in an unsigned long. Even still,
the behaviour of the following is undefined:
ptrdiff_t distance_a_to_d =
(long unsigned)&obj.d - (long unsigned)&obj.a;
The C++ Standard gives no indication whatsoever as to how an address
should be represented numerically. By adding 1 to the integer form of
an address, you could be adding half a byte for all you know, or a
quarter of a byte, or an eighth of a byte.
Of course it does. What do you think ptrdiff_t is for? Making
candy-floss?
Don't mention Windows to me. Microsoft and all of its programming
practises are utterly retarded.
I take any need to mention Microsoft as an argument in my favour.
Of course it is.
The address of any byte in memory (whether it be
part of a POD, intrinsic type, union, class object, whatever) can be
accurately stored in either of:
void*
char*
char signed*
char unsigned*
Insults designed to cover up weakness in argument or to try to bully
people into sharing your personal preferences are out of place. You have
made a succession of false claims in previous posts and continue to make
them in this one. A better quality of argument would impress me. Insults
don't. In fact the combination of your rudeness and inaccuracy makes me
reluctant to converse with you.
It may work perfectly, but it has unspecified behaviour. By 5.2.10/7 of
the C++ Standard:
"A pointer to an object can be explicitly converted to a pointer to an
object of different type. Except that converting an rvalue of type
"pointer to T1" to the type "pointer to T2" (where T1 and T2 are object
types and where the alignment requirements of T2 are no stricter than
those of T1) and back to its original type yields the original pointer
value, the result of such a pointer conversion is unspecified."
Since your code does not convert back to the original type, the result
is unspecified.
The right-hand side is not undefined, it is implementation-defined.
True enough, but, as I have shown above, it likewise guarantees nothing
about what happens to address values when a pointer is cast to a new
type (except that casting it back unchanged gives the original value).
No, it is for storing the result of pointer arithmetic. However, the
standard doesn't guarantee that it will be large enough to do so. By
Section 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."
Frederick Gotham said:I'm sorry about my attitude, I got a little worked up; I'll try no
let it happen again.
It doesn't make much sense that the Standard would provide a type for
pointer arithmetic, and then simply say "Oh yeah, by the way, this
isn't guaranteed to work".
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.