pointer casts(newbie)

K

Kai-Uwe Bux

would it be possible to cast pointers to any other type of pointer?
for example:
int * a cast to string * b?

Yes, but you could not do anything with the result except for casting it
back. More precisely, the standard guarantees that when you cast back to
the original type, you get the original value. No other guarantees are
made. In particular, deleting or dereferencing the pointer obtained from
the cast is undefined behavior. (That is only an approximation. The precise
rules depend on the pointer types involved and on the cast used. E.g., the
above does not apply to const_cast, but your example shows that you could
not mean that anyway.)

In short: don't cast unless you know exactly what you are doing.


Best

Kai-Uwe Bux
 
J

James Kanze

Yes, but you could not do anything with the result except for
casting it back. More precisely, the standard guarantees that
when you cast back to the original type, you get the original
value. No other guarantees are made.

That's not quite true. If you cast it to a character type, you
can access the individual bytes. Modifying them will result in
undefined behavior if you later try to use the object with its
original type, but something like:

template< typename T >
void
dump(
std::eek:stream& dest,
T const& obj )
{
IOSave saver( dest ) ;
dest.setf( std::ios::hex, std::ios::basefield ) ;
dest.fill( '0' ) ;
unsigned char const*current
= reinterpret_cast< unsigned char const* >( &obj ) ;
unsigned char const*end = current + sizeof( T ) ;
while ( current != end ) {
dest << std::setw( 2 ) << *current ;
++ current ;
if ( current != end ) {
dest << ' ' ;
}
}
}

is sometimes useful (and has fully defined behavior).

(Of course, the intent is that an implementation offer
additional guarantees; reinterpret_cast is, or should be, useful
in some very low-level, system specific code, like the
implementation of a garbage collector. But as you said, you
better really know what you're doing if you want to use it. And
exactly what guarantees the implementation offers.)
 
K

Kai-Uwe Bux

James said:
That's not quite true.

Right. As I said, in the part you snipped:

That is only an approximation. The precise rules depend on the pointer
types involved and on the cast used.

Note the dependence on the pointer type.
If you cast it to a character type, you
can access the individual bytes. Modifying them will result in
undefined behavior if you later try to use the object with its
original type, but something like:

template< typename T >
void
dump(
std::eek:stream& dest,
T const& obj )
{
IOSave saver( dest ) ;
dest.setf( std::ios::hex, std::ios::basefield ) ;
dest.fill( '0' ) ;
unsigned char const*current
= reinterpret_cast< unsigned char const* >( &obj ) ;
unsigned char const*end = current + sizeof( T ) ;
while ( current != end ) {
dest << std::setw( 2 ) << *current ;
++ current ;
if ( current != end ) {
dest << ' ' ;
}
}
}

is sometimes useful (and has fully defined behavior).

Nice. I agree that it is sometimes useful to read the underlying bytes of an
object.

IOSave ???


Best

Kai-Uwe Bux
 
T

Thomas J. Gritzan

Kai-Uwe Bux said:
James said:
template< typename T >
void
dump(
std::eek:stream& dest,
T const& obj )
{
IOSave saver( dest ) ;
dest.setf( std::ios::hex, std::ios::basefield ) ;
dest.fill( '0' ) ;
unsigned char const*current
= reinterpret_cast< unsigned char const* >( &obj ) ;
unsigned char const*end = current + sizeof( T ) ;
while ( current != end ) {
dest << std::setw( 2 ) << *current ;
++ current ;
if ( current != end ) {
dest << ' ' ;
}
}
}
[...]
IOSave ???

I bet it's a RAII class that restores the state of the ostream on exit,
so that the user of this function doesn't accidentally output numbers in
hex with fillchar '0'.

Is there a paper somewhere about techniques / things you can do with
RAII besides managing memory and object lifetime? Like
undoing/committing changes (in transactions), restoring stream states, etc.?
 
A

Alf P. Steinbach

* Kai-Uwe Bux:
Right. As I said, in the part you snipped:

That is only an approximation. The precise rules depend on the pointer
types involved and on the cast used.

Note the dependence on the pointer type.


Nice. I agree that it is sometimes useful to read the underlying bytes of an
object.

IOSave ???

Well, the most practically useful exception to the general rule (for
reinterpret_cast) is to cast from pointer to first member in POD struct, to
pointer to that POD struct, and vice versa.

This allows a kind of C-like simulation of inheritance.

I don't recall exactly how well-defined it is. Perhaps it was defined as
implementation defined but with guideline. But anyway it's practically
well-defined, due to the need to support C compatibility.


Cheers,

- Alf
 
J

James Kanze

I bet it's a RAII class that restores the state of the ostream
on exit, so that the user of this function doesn't
accidentally output numbers in hex with fillchar '0'.

Exactly. I've been using it for almost 15 years now. I've sort
of assumed that everyone has something like it in their toolkit.
Is there a paper somewhere about techniques / things you can
do with RAII besides managing memory and object lifetime? Like
undoing/committing changes (in transactions), restoring stream
states, etc.?

Well, in a certain sense, all use of RAII is a question of
undoing or committing changes in a transaction---even allocating
memory can be considered a change which you undo by freeing it.
Probably the most frequent use of RAII is something like
boost::scoped_lock, for mutexes. Another RAII class in my
toolkit include OutputFile (deletes the file in the destructor,
if commit hasn't been called---so you don't leave partially
written, incoherent files laying around in case of an error);
this one is associated with a SetOfOutputFiles, which ensures
all or nothing over several files. In some cases, it could also
be used to manage temporary files; I use a global
solution here (with an option to suppress the delete of the
files, for debugging purposes), but that's only valid for
programs which do something and then terminate; if a server
needs a temporary file to manage a request, it should use RAII.
I also use a somewhat extended form of RAII to manage the
context for logging (defines a "record" in the log, ensuring
that the record is written atomically in a single block, that
the first line gets the usual log header, and that following
lines are intented, and that the record ends with a '\n', even
if the client code doesn't provide one).

At a higher level, of course, all sorts of transaction
management, and even login management, can be handled, although
whether this is really RAII or not depends somewhat on the
organization of the code and the requirements of the
application. (In one application, I also used it to generate
change notifications. But that's really part of transaction
management as well.)

Interestingly, I very rarely use RAII for memory management.
Most of the time, if RAII would work, either I won't use dynamic
allocation at all, or it will be hidden in one of the standard
containers.
 
J

James Kanze

James Kanze wrote:

[...]
Nice. I agree that it is sometimes useful to read the
underlying bytes of an object.

Just one additional note: in my toolkit, this is present as a
class, with an overloaded <<, and a simple function which
returns an instance of the class (for type deduction), so you
can write things like:

std::cerr << "x = " << dump( x ) << std::endl ;

Useful for debugging very low-level objects.
 
K

Kai-Uwe Bux

James said:
Kai-Uwe Bux said:
James Kanze wrote:
template< typename T >
void
dump(
std::eek:stream& dest,
T const& obj )
{
IOSave saver( dest ) ;
dest.setf( std::ios::hex, std::ios::basefield ) ;
dest.fill( '0' ) ;
unsigned char const*current
= reinterpret_cast< unsigned char const* >( &obj ) ;
unsigned char const*end = current + sizeof( T ) ;
while ( current != end ) {
dest << std::setw( 2 ) << *current ;
++ current ;
if ( current != end ) {
dest << ' ' ;
}
}
}
[...]
IOSave ???
I bet it's a RAII class that restores the state of the ostream
on exit, so that the user of this function doesn't
accidentally output numbers in hex with fillchar '0'.

Exactly. I've been using it for almost 15 years now. I've sort
of assumed that everyone has something like it in their toolkit.

That sure is handy. Just added it :)


Thanks

Kai-Uwe Bux
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top