# Non conformant code but guaranteed to work?

**URL:** <https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511>\
**Category:** Uncategorized\
**Created:** [April 6, 2023, 7:44am UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511 "2023-04-06T07:44:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [April 6, 2023, 7:44am UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/1 "2023-04-06T07:44:10Z")

</div>

On a recent SO Q/A it came that the following code was not standard-conforming:

```auto
program foo
USE iso_c_binding

integer, allocatable :: a(:)
character, allocatable, target :: c(:)
integer, pointer :: p(:)

integer :: n=1000, i

a = [(i,i=1,n)]
c = transfer(a,c)

! ... then later on ...

call c_f_pointer( c_loc(c), p, [n] )
write(*,*) all(p == a) ! expected to print .true.

end program

```

It is non standard because for `c_f_pointer` the standard requires here `c` and `p` to have the same type (hence being just an equivalent of `p => c`), which is not the case.

> `C_F_POINTER(CPTR,FPRT,SHAPE)`: If the value of CPTR is the result of a reference to C\_LOC with a noninteroperable effective argument X, FPTR shall be a nonpolymorphic pointer with10 the same type and type parameters as X  
> [https://j3-fortran.org/doc/year/18/18-007r1.pdf](https://j3-fortran.org/doc/year/18/18-007r1.pdf)

Yet it compiles without any warning/error with ifort and gfortran, and prints the expected result (`.true.`)… which does not mean anything about the conformance.

But I wonder : how could it go wrong in practice? I cannot imagine a case where it wouldn’t work, actually.

There’s a variation of this code, using an interoperable intermediate type instead of `character`:

```auto
integer(c_signed_char), allocatable, target :: c(:)

```

Which is still non conformant in theory, but with a different case:

> `C_F_POINTER(CPTR,FPRT,SHAPE)`: If the value of CPTR is the C address of an interoperable data entity, FPTR shall be a data pointer with type and type parameter values interoperable with the type of the entity.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [April 6, 2023, 12:09pm UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/2 "2023-04-06T12:09:28Z")

</div>

> [@PierU](#):
>
> … But I wonder : how could it go wrong in practice? I cannot imagine a case where it wouldn’t work, actually…

For starters, `TRANSFER` semantics is such (weak/inadequate) a processor can possibly do things a programmer may not expect. A `LOGICAL` type is an immediate example where the attempted “round trip” can end up differently.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [April 6, 2023, 4:35pm UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/3 "2023-04-06T16:35:13Z")

</div>

I have some production code like this which I also believe is portable in a practical sense but is nonconforming for the same reason. The things that I watch for are big- and little-endian differences and cases where there are bits in the output of transfer() that are not touched. I don’t think those apply to your code, so in a practical sense, it looks safe to me.

As you probably know, the only thing that is guaranteed by the standard is that if you have a statement like

`c = transfer(a,c)`

and then sometime later (or even in the same expression) have a statement like

`b = transfer(c,b)`

then `a(:)` and `b(:)`, which are the same type and kind, should match. The standard does not say much else about what the intermediate `c(:)` looks like, and that is how your code works, it depends on how the bits are moved into `c(:)`.

You might leave some test code in your application that is executed rarely, say once per execution, on some small cases, where you can check for consistency. Your assumption is that if the small test passes, then all of the other larger cases are correct. That doesn’t catch every possible failure, of course, but it could catch things like the above (big- and little-endian dependencies, sign bits, padding bits, and so on).

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [April 7, 2023, 9:19am UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/4 "2023-04-07T09:19:47Z")

</div>

Indeed about `c = transfer(a,c)` the standard says:

> If the physical representation of the result [c] has the same length as that of SOURCE [a], the physical representation of the result [c] is that of SOURCE [a]"

So let’s look at that:

```auto
call c_f_pointer( c_loc(c), p, [n] ) ! non-standard conformant
call c_f_pointer( c_loc(a), p0, [n] ) ! standard conformant

```

If there are discrepancies between `p(:) and p0(:)` it means that the physical representations of `p0` and `p` differ a way or another. Hence that the physical representations of `a` and `c` differ: this contradicts the above citation of the standard. So, there shall not be any discrepancy between `p` and `p0`.

Is there something wrong in this reasonning?

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [April 7, 2023, 3:58pm UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/5 "2023-04-07T15:58:20Z")

</div>

> [@PierU](#):
>
> Indeed about `c = transfer(a,c)` the standard says:
> 
> > If the physical representation of the result [c] has the same length as that of SOURCE [a], the physical representation of the result [c] is that of SOURCE [a]"

I think in your example this length condition is not satisfied. At the time of the transfer(), `c(:)` is unallocated. Of course, the assignment itself then allocates `c(:)` to the correct length, but that happens after transfer() has done its thing. This might be just a technicality, but it might also be a way for padding bits or alignment to be introduced at the time of the transfer().

Just to give an example of a possible failure, supposed that integers must be aligned on 4-byte boundaries, but characters can be aligned at any byte. The `c(:)` array could then have an address that is not compatible with an integer address. In this case, the nonstandard

```auto
call c_f_pointer( c_loc(c), p, [n] )

```

might fail, perhaps silently, or perhaps with a seg fault.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [April 7, 2023, 7:38pm UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/6 "2023-04-07T19:38:27Z")

</div>

> [@RonShepard](#):
>
> I think in your example this length condition is not satisfied. At the time of the transfer(), `c(:)` is unallocated. Of course, the assignment itself then allocates `c(:)` to the correct length, but that happens after transfer() has done its thing.

I don’t think this is issue. In the text of the standard the “result” has to be understood as the raw output of the transfer() command, regardless what it is assigned to. However…

> [@RonShepard](#):
>
> This might be just a technicality, but it might also be a way for padding bits or alignment to be introduced at the time of the transfer().
> 
> Just to give an example of a possible failure, supposed that integers must be aligned on 4-byte boundaries, but characters can be aligned at any byte. The `c(:)` array could then have an address that is not compatible with an integer address. In this case, the nonstandard
> 
> ```auto
> call c_f_pointer( c_loc(c), p, [n] )
> 
> ```
> 
> might fail, perhaps silently, or perhaps with a seg fault.

Good point… And I think it answers my initial question: this is a case where it might fail.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [April 7, 2023, 9:36pm UTC](https://fortran-lang.discourse.group/t/non-conformant-code-but-guaranteed-to-work/5511/7 "2023-04-07T21:36:37Z")

</div>

> [@PierU](#):
>
> In the text of the standard the “result” has to be understood as the raw output of the transfer() command, regardless what it is assigned to.

I think you are right. I was thinking the length description was of the array `c(:)` as the mold argument, not of the result of the transfer() function, which itself involves some kind of memory allocation.

BTW, in the failure case, it might fail immediately, within `c_f_pointer()`, or it might fail some time later when the pointer `p(:)` is dereferenced and WW III is initiated.
