From: James Van Buskirk on
"Richard Maine" <nospam(a)see.signature> wrote in message
news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature...

> There is currently no portable standard-conforming way.

C:\gfortran\clf\sizetest>type sizetest1.f90
program sizetest1
use ISO_C_BINDING
implicit none
type contains_pointer
integer data
type(contains_pointer), pointer :: next
end type contains_pointer
integer, parameter :: ik1 = selected_int_kind(2)
type(contains_pointer) sp
type(contains_pointer), target :: ap(2)

! f90 way:
write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/)))
! f03 way:
write(*,'(a,i0)') 'In f03: ', &
transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
transfer(C_LOC(ap(1)),1_C_INTPTR_T)
! f08 way:
write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)
end program sizetest1

C:\gfortran\clf\sizetest>gfortran -Wall sizetest1.f90 -osizetest1

C:\gfortran\clf\sizetest>sizetest1
In f90: 16
In f03: 16
In f08: 16

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


From: glen herrmannsfeldt on
James Van Buskirk <not_valid(a)comcast.net> wrote:
(snip)

> ! f03 way:
> write(*,'(a,i0)') 'In f03: ', &
> transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
> transfer(C_LOC(ap(1)),1_C_INTPTR_T)

Last time this came up, I just put in 4.

It would have been nice to have C_PTRDIFF.

C_PTRDIFF(C_LOC(ap(2)),C_LOC(ap(1)))

-- glen
From: Richard Maine on
James Van Buskirk <not_valid(a)comcast.net> wrote:

> "Richard Maine" <nospam(a)see.signature> wrote in message
> news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature...
>
> > There is currently no portable standard-conforming way.

> ! f90 way:
> write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/)))

I didn't think of that one. Figures that you would. :-) I agree it is
standard conforming. I have used size(transfer(...)) in the past for
related purposes, so I suppose I ought to have thought of it. It was a
long time ago that I was doing that. I stopped it because, in addition
to being horribly messy (not just that line, but all the other parts
involved), it tended to crash compilers of the day. I think they have
since gotten better.

> ! f03 way:
> write(*,'(a,i0)') 'In f03: ', &
> transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
> transfer(C_LOC(ap(1)),1_C_INTPTR_T)

That's not standard conforming. It is highly likely to work, but is not
standard conforming. It assumes things about the internal representation
of C_PTR. They are things quite likely to be so, but they aren't
specified in the standard. This is a plausible alternative to the option
I mentioned of using a C function to do the subtraction (which is also
probably not strictly standard conforming, but is also likely to work).

> ! f08 way:
> write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)

Why C_SIZEOF instead of just STORAGE_SIZE, which I mentioned? C_SIZEOF
is mostly just a transformation of a special case. It is a
transformation that is often enough used to justify a special function
(at least that's my understanding of the argument for what otherwise
looks like redundant functionality).

Note that your version with C_SIZEOF is not actually conformant with the
f2008 draft because it does not meet the special-case requirements of
C_SIZEOF. In particular, sp is not interoperable.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: glen herrmannsfeldt on
Richard Maine <nospam(a)see.signature> wrote:
> James Van Buskirk <not_valid(a)comcast.net> wrote:

>> "Richard Maine" <nospam(a)see.signature> wrote in message
>> news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature...

>> > There is currently no portable standard-conforming way.

>> ! f90 way:
>> write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/)))

> I didn't think of that one. Figures that you would. :-) I agree it is
> standard conforming. I have used size(transfer(...)) in the past for
> related purposes, so I suppose I ought to have thought of it. It was a
> long time ago that I was doing that. I stopped it because, in addition
> to being horribly messy (not just that line, but all the other parts
> involved), it tended to crash compilers of the day. I think they have
> since gotten better.

"Standard conforming" is a complicated question in these cases.
In this case, it depends on the existence of the appropriate kind.
The unit for sizeof in C is the size of a char, but the main
requirement on that is that it be at least 8 bits.

>> ! f03 way:
>> write(*,'(a,i0)') 'In f03: ', &
>> transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
>> transfer(C_LOC(ap(1)),1_C_INTPTR_T)

> That's not standard conforming. It is highly likely to work, but is not
> standard conforming. It assumes things about the internal representation
> of C_PTR. They are things quite likely to be so, but they aren't
> specified in the standard. This is a plausible alternative to the option
> I mentioned of using a C function to do the subtraction (which is also
> probably not strictly standard conforming, but is also likely to work).

C only allows subtraction of pointers to different parts of the
same object, such as different elements of an array. That removes
some of the cases where this can fail. C also allows different
representation for pointers to different types. If I understand
it right, Fortran doesn't allow for that one. For example,
character pointers on word addressed machines might use other
bits to indicate the position in a word. I believe that C also
doesn't guarantee that there is such an integer type, but only says
what happens if there is such a type. It could be especially
interesting in the case of 32 bit far model IA32 code, where
pointers are 48 bits. (16 bit segment selector, 32 bit offset.)

>> ! f08 way:
>> write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)

> Why C_SIZEOF instead of just STORAGE_SIZE, which I mentioned? C_SIZEOF
> is mostly just a transformation of a special case. It is a
> transformation that is often enough used to justify a special function
> (at least that's my understanding of the argument for what otherwise
> looks like redundant functionality).

Again, there could be some interesting cases on word addressed
machines. C has the preprocessor macro CHAR_BIT indicating
the number of bits in a (char), and so the unit for sizeof.

> Note that your version with C_SIZEOF is not actually conformant with the
> f2008 draft because it does not meet the special-case requirements of
> C_SIZEOF. In particular, sp is not interoperable.

If there is no corresponding C type, then asking for the C sizeof
something doesn't make so much sense. There are some C cases
that I wonder about. In C, character constants, such as 'x', have
type int, and so sizeof('x')==sizeof(int). (As I understand it,
that isn't true in C++.) Enumeration constants also have sizeof(int),
though the appropriate variable can have a different size. C doesn't
allow pointers to constants, which avoids some problems that would
otherwise appear in those two cases.

-- glen
From: Phred Phungus on
James Van Buskirk wrote:
> "Richard Maine" <nospam(a)see.signature> wrote in message
> news:1jfwiq3.1154fi71vt5b5sN%nospam(a)see.signature...
>
>> There is currently no portable standard-conforming way.
>
> C:\gfortran\clf\sizetest>type sizetest1.f90
> program sizetest1
> use ISO_C_BINDING
> implicit none
> type contains_pointer
> integer data
> type(contains_pointer), pointer :: next
> end type contains_pointer
> integer, parameter :: ik1 = selected_int_kind(2)
> type(contains_pointer) sp
> type(contains_pointer), target :: ap(2)
>
> ! f90 way:
> write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/)))
> ! f03 way:
> write(*,'(a,i0)') 'In f03: ', &
> transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
> transfer(C_LOC(ap(1)),1_C_INTPTR_T)
> ! f08 way:
> write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)
> end program sizetest1
>
> C:\gfortran\clf\sizetest>gfortran -Wall sizetest1.f90 -osizetest1
>
> C:\gfortran\clf\sizetest>sizetest1
> In f90: 16
> In f03: 16
> In f08: 16
>

$ gfortran -D_GNU_SOURCE -Wall -Wextra jb1.f90 -o out
jb1.f90:19.32:

write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)
1
Error: Function 'c_sizeof' at (1) has no IMPLICIT type
$ cat jb1.f90
program sizetest1
use ISO_C_BINDING
implicit none
type contains_pointer
integer data
type(contains_pointer), pointer :: next
end type contains_pointer
integer, parameter :: ik1 = selected_int_kind(2)
type(contains_pointer) sp
type(contains_pointer), target :: ap(2)

! f90 way:
write(*,'(a,i0)') 'In f90: ', size(transfer(sp,(/1_ik1/)))
! f03 way:
write(*,'(a,i0)') 'In f03: ', &
transfer(C_LOC(ap(2)),1_C_INTPTR_T)- &
transfer(C_LOC(ap(1)),1_C_INTPTR_T)
! f08 way:
write(*,'(a,i0)') 'In f08: ', C_SIZEOF(sp)
end program sizetest1

! gfortran -D_GNU_SOURCE -Wall -Wextra jb1.f90 -o out
$


I don't see an obvious culprit for the error.
--
fred