iterators, pointers and (T*)-1

G

Gianni Mariani

I'm looking at templatizing some code that uses pointers and iterators.

There are 3 kinds of values for pointers.

- Null
- Invalid ( the value is ((T*)-1) )
- Valid


Null indicates that the pointer is Null - cool.

Invalid indicates that the pointer is uninitialized - using this value
fails asserts.

Valid points to an object.


Now I want to use iterators and I don't have access to a container.

I was thinking I could use:

typedef map<X>::iterator container_iterator; // any container

union Ptr
{
ptr_diff_t val;
container_iterator ptr;
};


bool IsNull( const Ptr & ptr )
{
assert( ptr.val != -1 );
return ( ptr.val == 0 );
}

container_iterator::value_type & dereference ( Ptr & ptr )
{
assert( ptr.val != -1 );
return * ptr.ptr;
}

Did I break somthing ? I probably did. Firstly, a container_iterator
may occupy more space than a ptr_diff_t and even if it did not, the are
assuptions here that are probably not universally true.

The question is, am I missing somthing regarding iterators ? Is there
a way to initialize an STL iterator to a "null" and also an "invalid"
value without creating a class that is larger than the iterator itself ?

I would find it very useful if you could contain other interesting
values for iterators.


The example for a POD pointer is easy. This code should work on any
conforming C++ compiler.

typedef value_type * pointer_type;

struct Ptr
{
pointer_type ptr;
};

bool IsNull( const Ptr & ptr )
{
assert( ptr.ptr != ( pointer_type * ) -1);
return ( ptr.val == 0 );
}

container_iterator::value_type & dereference ( Ptr & ptr )
{
assert( ptr.ptr != ( pointer_type * ) -1);
return * ptr.ptr;
}
 
G

Gianni Mariani

Ron said:
No guarantee that you can cast -1 to a pointer type and get the value back.

True, but that's not what it's doing.

The assumption is:

((T*)-1) == ((T*)-1)

A problem may arise in the unlikely event that ((T*)-1) is by some
chance a valid pointer - I won't loose sleep on that.
 
A

Andrew Koenig

Gianni Mariani said:
back.

True, but that's not what it's doing.

The assumption is:

((T*)-1) == ((T*)-1)

A problem may arise in the unlikely event that ((T*)-1) is by some
chance a valid pointer - I won't loose sleep on that.

A more likely outcome is the compiler refusing to compile your program
outright.

Implementations are not required to accept programs that cast nonzero
integral values to pointers.
 
D

David A. Ferguson

Implementations are not required to accept programs that cast nonzero
integral values to pointers.

Then what is the proper way to form a pointer to known memory address?

For example, I know that my data aquition board is at memory address
0xC8000. I need to construct a pointer to this address.

Cheers...David
 
G

Gianni Mariani

Andrew said:
A more likely outcome is the compiler refusing to compile your program
outright.

Implementations are not required to accept programs that cast nonzero
integral values to pointers.

2 things -

a) Noisy refusal to compile is easy to identify and does not cause
mysterious problems and are easy to fix.

b) I know of no compiler that would do what you say. Do you have an
example ? What does the standard say about it ?
 
R

Ron Natalie

Andrew Koenig said:
A more likely outcome is the compiler refusing to compile your program
outright.
And an easy way around it would just be to construct a sentinal object
that's never used for anything other than the invalid check.
 
R

Ron Natalie

David A. Ferguson said:
Then what is the proper way to form a pointer to known memory address?

For example, I know that my data aquition board is at memory address
0xC8000. I need to construct a pointer to this address.

There is no PORTABLE way to do that, although on many machines casting
an unsigned integer to the appropriate pointer type will work. Of the other
issue (since the above looks oddly like a PC memory address) that you actually
have that address in your address space. On other than the DOS throwbacks
physical memory addressess are not directly accessible to a random user
program.
 
G

Gianni Mariani

Ron said:
And an easy way around it would just be to construct a sentinal object
that's never used for anything other than the invalid check.

The mmap() and shmat() system calls comes to mind as an implementation
that requires comparison with a ((void *)-1) value to determine error.

Hence I believe that any compiler that does not handle

((T*)-1) == ((T*)-1)

is basically broken since legacy code will not compile correctly. It's
all nice to say that the compiler can do whatever it wants but it had
better manage all legacy code.

I really wish someone would answer the original question. I fear that I
will be dissapointed. I want stl iterators to have a similar behavior
to POD pointers when it comes to "null" (and "invalid"). Breaking
things into a sentinal value seems to make little sense when there
exists a previous paradigm (the null) that is generally effective and
well understood.
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Gianni Mariani escribió:
I really wish someone would answer the original question. I fear that I
will be dissapointed. I want stl iterators to have a similar behavior
to POD pointers when it comes to "null" (and "invalid"). Breaking

I think the only way is write your own version of the containers and his
iterators.

Regards.
 
R

Ron Natalie

Gianni Mariani said:
b) I know of no compiler that would do what you say. Do you have an
example ? What does the standard say about it ?

I don't think the compiler is free to NOT compile it. However, the behavior of
such mapping is implementation defined. It could result in some kind of pointer
trap representation.
 
G

Gianni Mariani

Julián Albo said:
Gianni Mariani escribió:




I think the only way is write your own version of the containers and his
iterators.

Wrong ! The other way is to convice the standards comittee to change add
features to iterators. Just a sec, .... thinking ...., na, you're right.
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top