Comparing pointers

J

J Caesar

In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?

JC.
 
I

Ivar Rosquist

In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

Really!? How have I managed to do so all these years?

Pointers are just addresses - usually 32-, these days more and
more, 64-bit unsigned integers. Which you can always compare at will.
Usually you'll want for them to be pointers to the same type of data, of
course.
 
M

Malcolm McLean

J Caesar said:
In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?
It can't be done. Or rather, it can't be done portably. To do it
non-portably is probably either trivial or the compiler has no issues with
pointers to different blocks.

The "no comparison" rule is a kludge to allow for funny architectures. It
becomes a nuisance when you need to know whether a pointer comes from a
certain block or not. However you don't need that information very
frequently, and on balance it is probably better to make the compiler easier
to implement or code to run faster.
 
R

Richard Tobin

In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?

You're right, you can't. But why do you want to? What are you trying
to achieve?

Note that you can compare pointers for equality even if they are
from different objects.

-- Richard
 
M

Malcolm McLean

Ivar Rosquist said:
Really!? How have I managed to do so all these years?
It is undefined behaviour. Realistically a flat memory architecture is just
going to do a starightforwards subtraction of bits. However it could trap or
return funny results on some machines.
 
F

Flash Gordon

J Caesar wrote, On 05/06/07 22:44:
In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?

Your initial thought is correct, you can't do the check in standard C.
 
W

Walter Roberson

Really!? How have I managed to do so all these years?
Non-portably.

Pointers are just addresses - usually 32-, these days more and
more, 64-bit unsigned integers. Which you can always compare at will.
Usually you'll want for them to be pointers to the same type of data, of
course.

Pointers are not necessarily just addresses: pointers may be opaque
with storage silently managed "under the hood", or pointers may
include type information, or pointers may include not have the
address information in numeric order (e.g., Cray put the character
offset bits in the upper byte). Or, as was common on VMS, pointers
might be the address of "descriptors" -- a block of data that
describes the type and array and virtual memory address of the
actual storage. And when you are working with a Harvard architecture,
a pointer to a function could have exactly the same numeric value
as a pointer to an object: since C does not provide any operations
that translate between function pointers and object pointers, there
is no conflict in having a function pointer with the same value
as an object pointer, with the code knowing which kind of instructions
are needed for the correct kind of access.
 
J

J Caesar

You're right, you can't. But why do you want to? What are you trying
to achieve?

Note that you can compare pointers for equality even if they are
from different objects.

This gives one method: write a wrapper to malloc to store a pointer to
each block allocated together with the size of the block. Then do an
exhaustive search over all pointers to all elements of all blocks
allocated to find which blocks p and q are in (only needs you to compare
each pointer for equality with p or q, which is legal). And you're done.

I see two problems: 1) very inefficient if large tracts of memory are
allocated; 2) fails if p or q point inside statically allocated arrays
rather than malloc()ed blocks.

JC.
 
K

Keith Thompson

J Caesar said:
In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?

I don't believe there's any way to do this in standard C. Attempting
to compare the pointers invokes undefined behavior; there's no way to
detect that before running into it.
 
V

Vinoj

In C you can compare two pointers, p<q, as long as they come from the
same array or the same malloc()ated block. Otherwise you can't.

What I'd like to do is write a function
int comparable(void *p, void *q)
that will take any two pointers and decide whether they can be compared
or not.

I really can't think how to do this - any suggestions?

JC.

Typecast the pointers to 'unsigned int' before comparing them.


Thanks, Regards,
Vinoj
 
I

Ian Collins

Vinoj said:
Typecast the pointers to 'unsigned int' before comparing them.
Cast, not typecast. This is bad advice for at least three reasons:

Appropriate pointers can be compared without any casts.

On many systems, including the one I'm typing this on, pointers are
larger than unsigned int.

Casting hides the intent.
 
V

Vinoj

Cast, not typecast. This is bad advice for at least three reasons:

Appropriate pointers can be compared without any casts.

On many systems, including the one I'm typing this on, pointers are
larger than unsigned int.

Casting hides the intent.

I am yet to buy a 64-bit system. Due to the lack of OS support I am
unable to buy one. I just want to run Linux on a 64-bit system. Can
you please provide me a pointer, where I can readily get IA-64 Linux
Distributable. It seems there is no support for DOS in 64 bit OS, so
I cannot get a DOS box on Windows if I have a Dual Boot? I just dont
want to go for a expensive server models that take up my room space
where I already I have 2 machines one Pentium 4 HT and one Celeron,
for device driver WinDBG and such stuff.

Thanks, Regards,
Vinoj
 
R

Richard Heathfield

Vinoj said:
Typecast the pointers to 'unsigned int' before comparing them.

Presuming you mean "cast", how would that help to establish whether they
can be compared /without/ the cast? And if your purpose is to avoid the
question altogether by making sure they can *always* be compared,
consider the possibility that the cast loses information - for example,
imagine a system with 16-bit unsigned ints and 20-bit pointers. (No,
that wasn't an accidental choice.)
 
P

pete

Ian said:
Cast, not typecast. This is bad advice for at least three reasons:

Appropriate pointers can be compared without any casts.

On many systems, including the one I'm typing this on, pointers are
larger than unsigned int.

Casting hides the intent.

#4 The result of the comparison of the resulting 'unsigned int'
values, doesn't imply which pointer has the higher address.
 
K

Keith Thompson

Vinoj said:
I am yet to buy a 64-bit system. Due to the lack of OS support I am
unable to buy one. I just want to run Linux on a 64-bit system. Can
you please provide me a pointer, where I can readily get IA-64 Linux
Distributable.

Your question has nothing to do with C, or even with this discussion.
Try a Linux-specific newsgroup.
 
G

George Neuner

This gives one method: write a wrapper to malloc to store a pointer to
each block allocated together with the size of the block. Then do an
exhaustive search over all pointers to all elements of all blocks
allocated to find which blocks p and q are in (only needs you to compare
each pointer for equality with p or q, which is legal). And you're done.

p or q may be interior pointers to a malloc'd block.

Just comparing them for equality with the base address won't work.
You need to compare base <= p < (base+size), at which point you're
back to undefined behavior if p is not a pointer into the block.

There isn't any way to do it portably unless you control allocation.
If you use your own heap functions and arrange that all allocations
are made from an array under your control, then you can safely compare
any pointers into those blocks.

But it still won't help in the general case. Technically, by the
standard, comparing unrelated pointers in any way (even for equality)
produces undefined behavior. The exception is that any pointer may be
compared against the constant NULL ... but then the value of NULL is
implementation defined and _not_ guaranteed to be zero.


People have been writing technically non-portable pointer code since
the beginning. Most have just been lucky that the platforms they
targeted had memory layouts which coincidentally corresponded to the
definition of a C array and pointers were simple addresses. As Walter
Roberson mentioned earlier, there are systems in which the notion of a
pointer is more complicated. There are even some systems in which
memory is not organized as an array.

George
 
C

Clark Cox

But it still won't help in the general case. Technically, by the
standard, comparing unrelated pointers in any way (even for equality)
produces undefined behavior.

No, comparing for equality is specifically allowed by the standard.
 

Ask a Question

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.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top