Neil Carlson writes:
> I found TRANSFER being cleverly used to copy addresses between
> different types....
> Comments are encouraged. I'd especially like to hear from the real experts
> whether this is a legitimate use of TRANSFER, whose complete behavior is
> far from clear to me. I suspect that the behavior I'm relying on is not
> guaranteed by the standard.
This is the kind of thing I used to do many years ago before I got
tired of debugging compilers. Perhaps they have gotten better in
recent years, but this used to be a "good" source of compiler bugs.
Note that one thing it is *VERY* likely to break is garbage
collection schemes.
The code as you show it appears to make an assumption that the
standard explicitly disclaims. You are assuming that all pointers
have the same number of bits. I wouldn't count on that - the standard
is pretty explicit (for the standard) in saying that you can't.
Admitedly, I think (but do not know) that it is probably true for
most implementations provided that you at least restrict yourself
to pointers of the same rank - for different ranks, I think you'd be
in serious trouble.
To have muchpretext of standard conformance, you have to deal with
the unknown size of pointers. My old, no-longer-used code used to do
something like the following (written on the fly and untested):
Since the size of the pointer is unknown, you'll need a dynamically
sized array of something to hold even a scalar pointer. I arbitrarily
choose integer type for this array, though any other type would also
do. I made it a pointer so it could be dynamically allocated (recall
the current restrictions on allocatable components).
type(whatever), pointer :: original_ptr
type whatever_ptr
type(whatever), pointer:: ptr
end type
integer, pointer :: storage(:)
type(whatever_ptr) :: x
!-- First we figure out what we need for the size.
!-- Note that this use of TRANSFER() as an actual argument for
!-- size blows many compiler's minds, although it is legal.
!-- I suppose that if one was concerned about efficiency, one
!-- could do this once ahead of time and save the result.
!-- But then if one is concerned about efficiency, one is probably
!-- going to be pretty disappointed in this whole approach.
x%ptr => original_ptr
i = size(transfer(x,storage))
allocate(storage(i))
!-- Now that we have something big enough to store the result, we
!-- get to do the transfer all over again.
storage = transfer(x,storage)
....
Now we can copy the storage around as an array of integer. If we
ever want to get at the target of the original_ptr, we need to
first go through another ugly and non-intuitive sequence to get
the bits back in a pointer of type whatever.
I don't do this any more. Caveat emptor.
P.S. F2k ought to make this a lot easier.
--
Richard Maine | Good judgement comes from experience;
[log in to unmask] | experience comes from bad judgement.
| -- Mark Twain
|