I am struggling to understand the different behavior of => and = when assigning one pointer to another in Fortran 95. I.e. say I have a derived data type foo, what then is the difference between the last two lines in the following snippet, are they equivalent?
type(foo), target :: f
type(foo), pointer :: p1, p2
f = foo(...)
p1 => foo
p2 => p1
p2 = p1
No, they are absolutely not equivalent and mistaking them has large consequences (like Fortran Functions with a pointer result in a normal assignment).
= is the assignment of value (or just assignment if you want to be exact), it will take the value stored on the right hand side and copy it to the left hand side. If the left hand side is a pointer, it will copy the value to the target of the pointer. If the pointer did not point anywhere (null) or to some undefined place (a garbage address), it is an undefined behaviour but a crash is very likely.
=> is the pointer assignment, the left hand side must be a pointer, the right hand side must be a target or a pointer. The pointer on the left hand side will point to the target (or the target of the pointer) on the right hand side. If the pointer on the left was already pointing to some memory, that was previously allocated by an allocate statement through a pointer, and it was the only pointer pointing there, that memory will be lost (a memory leak).
Related
It seems that both ways to create a new object pointer with all "0" member values, both returns a pointer:
type T struct{}
...
t1:=&T{}
t2:=new(T)
So what is the core difference between t1 and t2, or is there anything that "new" can do while &T{} cannot, or vice versa?
[…] is there anything that "new" can do while &T{} cannot, or vice versa?
I can think of three differences:
The "composite literal" syntax (the T{} part of &T{}) only works for "structs, arrays, slices, and maps" [link], whereas the new function works for any type [link].
For a struct or array type, the new function always generates zero values for its elements, whereas the composite literal syntax lets you initialize some of the elements to non-zero values if you like.
For a slice or map type, the new function always returns a pointer to nil, whereas the composite literal syntax always returns an initialized slice or map. (For maps this is very significant, because you can't add elements to nil.) Furthermore, the composite literal syntax can even create a non-empty slice or map.
(The second and third bullet-points are actually two aspects of the same thing — that the new function always creates zero values — but I list them separately because the implications are a bit different for the different types.)
For structs and other composites, both are same.
t1:=&T{}
t2:=new(T)
//Both are same
You cannot return the address of un-named variable initialised to zero value of other basic types like int without using new. You would need to create a named variable and then take its address.
func newInt() *int {
return new(int)
}
func newInt() *int {
// return &int{} --> invalid
var dummy int
return &dummy
}
See ruakh's answer. I want to point out some of the internal implementation details, though. You should not make use of them in production code, but they help illuminate what really happens behind the scenes, in the Go runtime.
Essentially, a slice is represented by three values. The reflect package exports a type, SliceHeader:
SliceHeader is the runtime representation of a slice. It cannot be used safely or portably and its representation may change in a later release. Moreover, the Data field is not sufficient to guarantee the data it references will not be garbage collected, so programs must keep a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
If we use this to inspect a variable of type []T (for any type T), we can see the three parts: the pointer to the underlying array, the length, and the capacity. Internally, a slice value v always has all three of these parts. There's a general condition that I think should hold, and if you don't use unsafe to break it, it seems by inspection that it will hold (based on limited testing anyway):
either the Data field is not zero (in which case Len and Cap can but need not be nonzero), or
the Data field is zero (in which case the Len and Cap should both be zero).
That slice value v is nil if the Data field is zero.
By using the unsafe package, we can break it deliberately (and then put it all back—and hopefully nothing goes wrong while we have it broken) and thus inspect the pieces. When this code on the Go Playground is run (there's a copy below as well), it prints:
via &literal: base of array is 0x1e52bc; len is 0; cap is 0.
Go calls this non-nil.
via new: base of array is 0x0; len is 0; cap is 0.
Go calls this nil even though we clobbered len() and cap()
Making it non-nil by unsafe hackery, we get [42] (with cap=1).
after setting *p1=nil: base of array is 0x0; len is 0; cap is 0.
Go calls this nil even though we clobbered len() and cap()
Making it non-nil by unsafe hackery, we get [42] (with cap=1).
The code itself is a bit long so I have left it to the end (or use the above link to the Playground). But it shows that the actual p == nil test in the source compiles to just an inspection of the Data field.
When you do:
p2 := new([]int)
the new function actually allocates only the slice header. It sets all three parts to zero and returns the pointer to the resulting header. So *p2 has three zero fields in it, which makes it a correct nil value.
On the other hand, when you do:
p1 := &[]int{}
the Go compiler builds an empty array (of size zero, holding zero ints) and then builds a slice header: the pointer part points to the empty array, and the length and capacity are set to zero. Then p1 points to this header, with the non-nil Data field. A later assignment, *p1 = nil, writes zeros into all three fields.
Let me repeat this with boldface: these are not promised by the language specification, they're just the actual implementation in action.
Maps work very similarly. A map variable is actually a pointer to a map header. The details of map headers are even less accessible than those of slice headers: there is no reflect type for them. The actual implementation is viewable here under type hmap (note that it is not exported).
What this means is that m2 := new(map[T1]T2) really only allocates one pointer, and set that pointer itself to nil. There is no actual map! The new function returns the nil pointer, and m2 is then nil. Likewise var m1 map[T1]T2 just sets a simple pointer value in m1 to nil. But var m3 map[T1]T2{} allocates an actual hmap structure, fills it in, and makes m3 point to it. We can once again peek behind the curtain on the Go Playground, with code that is not guaranteed to work tomorrow, to see this in effect.
As someone writing Go programs, you don't need to know any of this. But if you have worked with lower-level languages (assembly and C for instance), these explain a lot. In particular, these explain why you cannot insert into a nil map: the map variable itself holds a pointer value, and until the map variable itself has a non-nil pointer to a (possibly empty) map-header, there is no way to do the insertion. An insertion could allocate a new map and insert the data, but the map variable wouldn't point to the correct hmap header object.
(The language authors could have made this work by using a second level of indirection: a map variable could be a pointer pointing to the variable that points to the map header. Or they could have made map variables always point to a header, and made new actually allocate a header, the way make does; then there would never be a nil map. But they didn't do either of these, and we get what we get, which is fine: you just need to know to initialize the map.)
Here's the slice inspector. (Use the playground link to view the map inspector: given that I had to copy hmap's definition out of the runtime, I expect it to be particularly fragile and not worth showing. The slice header's structure seems far less likely to change over time.)
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
p1 := &[]int{}
p2 := new([]int)
show("via &literal", *p1)
show("\nvia new", *p2)
*p1 = nil
show("\nafter setting *p1=nil", *p1)
}
// This demonstrates that given a slice (p), the test
// if p == nil
// is really a test on p.Data. If it's zero (nil),
// the slice as a whole is nil. If it's nonzero, the
// slice as a whole is non-nil.
func show(what string, p []int) {
pp := unsafe.Pointer(&p)
sh := (*reflect.SliceHeader)(pp)
fmt.Printf("%s: base of array is %#x; len is %d; cap is %d.\n",
what, sh.Data, sh.Len, sh.Cap)
olen, ocap := len(p), cap(p)
sh.Len, sh.Cap = 1, 1 // evil
if p == nil {
fmt.Println(" Go calls this nil even though we clobbered len() and cap()")
answer := 42
sh.Data = uintptr(unsafe.Pointer(&answer))
fmt.Printf(" Making it non-nil by unsafe hackery, we get %v (with cap=%d).\n",
p, cap(p))
sh.Data = 0 // restore nil-ness
} else {
fmt.Println("Go calls this non-nil.")
}
sh.Len, sh.Cap = olen, ocap // undo evil
}
I have a pointer uvw(:,:) which is two-dimensional, and I got a 1d buffer array x(:).
Now I need to point uvw(1,:)=>x(1:ncell) and uvw(2,:)=>x(ncell+1:ncell*2) etc.
I made a very simple example. I know that array of pointers does not work, but does anybody have an idea how this can be worked around?
PS: For a pragmatic reason I do not want to wrap my uvw with a declared type. ( i am changing some bit of code, and need uvw as 2D pointer. Currently is an array, and my idea is to avoid changing the way uvw is being used as it being used thousands of times)
program test
real, allocatable,target :: x(:)
real, pointer :: ptr(:,:)
allocate(x(100) )
x = 1.
ptr(1,:) => x(1:10)
end program
The error message says:
`error #8524: The syntax of this data pointer assignment is incorrect:
either 'bound spec' or 'bound remapping' is expected in this context.
[1]
ptr(1,:) => x(1:10)
----^`
You are trying to perform pointer bounds remapping, but you have the incorrect syntax and approach.
Pointer bounds remapping is a way to have the shape of the pointer different from that of the target. In particular, the rank of the pointer and target may differ. However, in such an assignment it is necessary to explicitly specify the lower and upper bounds of the remapping; it isn't sufficient to use : by itself.
Also, you'll need to assign the whole pointer in one go. That is, you can't have "the first ten elements point to this slice, the next ten to this slice" and so on in multiple statements.
The assignment statement would be
ptr(1:10,1:10) => x
Note, that this also means that you can't actually have what you want. You are asking for the elements ptr(1,1:10) to correspond to x(1:10) and ptr(2,2:10) to correspond to x(11:20). That isn't possible: the array elements must match in order: ptr(1:10,1) being the first ten elements of ptr must instead be associated with the first ten elements x(1:10). The corrected pointer assignment above has this.
If you prefer avoiding a pointer, then the UNION/MAP is an option depending on compiler. It was added to gfortran a while ago... then you can think of the array as a rank=2 but also use the vector (Rank=1) for SIMD operations.
All this assumes that one wants to avoid pointers...
I'm looking through some old Fortran 90 code and have come across the => symbol:
var => item
It looks like it's being used for some sort of assignment.
Searching Google for "arrow symbol Fortran" or "equals greater than symbol Fortran" gives me no related material.
=> appears in six contexts as a syntactic element in modern Fortran, many, but not all, related to pointers: pointer assignment; pointer initialization; procedure (pointer) declaration; type-bound procedure declaration; association; renaming. There is close connection between most of these. Loosely, in many => can be viewed as providing an alternative temporary or permanent means of referencing another entity. In none, however, is => acting as an operator.1
Pointer assignment
Pointer assignment is one of the traditional appearances of =>, appearing in Fortran 90. It is used to associate a pointer with a target, and is explained in another answer.
Use association renaming
Renaming of entities use associated involves the element => and is the other appearance in Fortran 90/95 code. Such use statements are like
use mod_a, c=>a
use mod_b, only : cc => bb
Following such a use statement the module entities a and bb are known by the local names c and cc.
Pointer initialization
Pointer initialization is much like pointer assignment where => appears. Pointer initialization defines the initial pointer association of the pointer. We see this in statements such as
real, target :: a
real, pointer :: b=>a
real, pointer :: c=>NULL()
With this explicit initializtion, the pointer b here is initially associated with a and the pointer c is initially unassociated. These two forms are helpful in modern Fortran in that in Fortran 90 a pointer always starts life initially of undefined association status. Here we know that b and c have defined pointer association status, and we can use ASSOCIATED.
For derived type components such syntax gives default initialization.
Procedure declaration
Much as with explicit/default initialization for data objects => features in defining the initial association of a procedure pointer.
procedure(proc_interface), pointer :: proc1 => donkey
procedure(proc_interface), pointer :: proc2 => null()
Here, proc1 is again initially associated with the procedure donkey and we can have such things as
call proc1(...)
much as we could when proc1 is pointer assigned with donkey outside the declaration statement. proc2 is, as expected, initially not associated.
As with data object components of derived types => can feature in setting the initial association of a derived type's procedure pointer component:
type a
procedure(proc_interface), pointer :: proc => donkey
end type a
Type-bound procedure declaration
Conceptually related to the above is the use of => in declaring type-bound procedures.
type a
contains
procedure :: proc => donkey
generic :: assignment(=) => type_a_eq
end type a
Here in the type a proc is a binding name so that b%proc (for b an entity of type a) is a procedure reference. We also, through type_a_eq, have defined assignment with entities of type a on the left-hand side.
Association
=> appears in four association contexts. The associate, change team, select type and select rank constructs associate a name with a selector.
From Fortran 2003 we have
associate (a => 1+2)
... ! In this block we have an entity named a
end associate
and
class(*) b ! b is unlimited polymorphic
select type (a => b)
type is (real)
... ! a is a non-polymorphic real here
end select
Introduced in Fortran 2018 we have
dimension(..) b ! b is assumed rank
select rank (a => b)
rank (1)
... ! a is a rank-1 array here
end select
and
change team (team_value, a[*] => b)
... ! In this block we have a coarray named a
end team
These associations differ from pointers. a in the associate block needn't be (and in the example above isn't) a variable.
[1] The concept of operator is precisely defined in the Fortran language, such as in 3.2.4 of the Fortran 2008 specification. Unlike many other languages, assignment (with =) itself is not an operation, but a statement. In C-like languages we can have (a=b) as an expression returning a result: this is not the case in Fortran. The same holds for pointer assignment in Fortran. The other cases above are wholly distinct from this idea of assignment. In Fortran, even = appearing in initialization is not the same thing as assignment. => cannot be viewed as having one effect.
Surprisingly, searching "equals arrow symbol Fortran" yields some results.
"=>" is commonly referred to as the pointer assignment operator.
(Though it is not truly an operator as it returns no value.)
It is used to associate a chosen reference name with a target:
reference => target
The above can be read as "reference refers to target"
Most often this reference occurs in the form of a pointer. In this case you could say "reference points to target". This is a helpful way to remember what this operator does as its literal appearance is of an arrow pointing from reference to target.
Further Uses
Additional uses including making local aliases for various items such as module components, procedures, and even arbitrary expressions. For a full explanation of all of these uses see this answer.
Pointer assignment vs. Traditional Assignment (=)
Here's a quick example from the above link that illustrates how pointer assignment differs from classic assignment ("="). Basically this shows that once a target has been established, the pointer is treated as that target for basic statements.
pt => x ! pt points to x
y = pt ! y equals x
pt => y ! pt points to y
pt = 17 ! y equals 17
Other Resources:
General documentation on Fortran pointers
When I pass a pointer (pointing to an object) to a called function as a parameter, why don't the object's attributes get copied? Is there a practical reason why this doesn't happen?
For example, if x is a pointer to an object, then the assignment x=y within the called function is not visible to the calling function. Yet, the assignment x.f=3 is visible (f is an attribute).
Thanks!
A pointer (in c and c++ and most other languages) is variable that points to an adress in memory, where the actual object resides.
Assigning one pointer to another just copies that address from one pointer to the other. Passing a pointer p to a function, where the corresponding parameter is called x results in two pointers pointing to the same address/object: one inside the calling function (p) and one inside the called one (x), but you still have only one object (obj1).
Now, x.f=3 (or c->f=3 in c/c++ syntax) means:
"Assign 3 to the attribute f of the object x points to". As this is the same object, p points to, you can observe that change also via p.
However, when you have another pointer y inside the function that points to a DIFFERENT object (obj2), and you assign that pointer to x, you do not copy the contents of obj2 to obj1, but you are only copying the ADDRESS of obj2 into x and leave obj1 unchanged. Now x points to a differen object than p does and as a result you won't observe any changes via p afterwards.
That's my first question post ever ... don't be cruel, please.
My problem is the following. I'd like to assign a fortran pointer as an expression. I think that's not possible by simple fortran techniques. But since new fortran versions seem to provide ways to handle things used in C and C++ (like c_ptr and c_f_pointer ... ), maybe someone knows a way to solve my problem. (I have not really in idea about C, but I read that pointer arithmetic is possible in C)
To make things more clear, here is the code which came to my mind immediately but isn't working:
program pointer
real(8),target :: a
real(8),pointer :: b
b=>a*2.0d0 ! b=>a is of course working
do i=1,10
a=dble(i)*2.0d0
write(*,*)b
end do
end program
I know that there are ways around this issue, but in the actual program, all of which came to my mind, would lead to much longer computation time and/or quite wiered code.
Thanks, a lot, in advance!
Best, Peter
From Michael Metcalf,
Pointers are variables with the POINTER attribute; they are not a distinct data type (and so no 'pointer arithmetic' is possible).
They are conceptually a descriptor listing the attributes of the objects (targets) that the pointer may point to, and the address, if any, of a target. They have no associated storage until it is allocated or otherwise associated (by pointer assignment, see below):
So your idea of b=>a*2 doesn't work because b is being assigned to a and not given the value of a.
Expression, in general (there two and a half very significant exceptions), are not valid pointer targets. Evaluation of an expression (in general) yields a value, not an object.
(The exceptions relate to the case where the overall expression results in a reference to a function with a data pointer result - in that case the expression can be used on the right hand side of a pointer assignment statement, or as the actual argument in a procedure reference that correspond to a pointer dummy argument or [perhaps - and F2008 only] in any context where a variable might be required, such as the left hand side of an ordinary assignment statement. But your expressions do not result in such a function reference and I don't think the use cases are relevant to what you wnt to do. )
I think you want the value of b to change as the "underlying" value of a changes, as per the form of the initial expression. Beyond the valid pointer target issue, this requires behaviour contrary to one of the basic principles of the language (most languages really) - evaluation of an expression uses the value of its primaries at the time the expression is evaluation - subsequent changes in those primaries do not result in a change in the historically evaluated value.
Instead, consider writing a function that calculates b based on a.
program pointer
IMPLICIT NONE
real(8) :: a
do i=1,10
a=dble(i)*2.0d0
write(*,*) b(a)
end do
contains
function b(x)
real(kind(a)), intent(in) :: x
real(kind(a)) :: b
b = 2.0d0 * x
end function b
end program
Update: I'm getting closer to what I wanted to have (for those who are interested):
module test
real,target :: a
real, pointer :: c
abstract interface
function func()
real :: func
end function func
end interface
procedure (func), pointer :: f => null ()
contains
function f1()
real,target :: f1
c=>a
f1 = 2.0*c
return
end function f1
end module
program test_func_ptrs
use test
implicit none
integer::i
f=>f1
do i=1,10
a=real(i)*2.0
write(*,*)f()
end do
end program test_func_ptrs
I would be completely satisfied if I could find a way to avoid the dummy arguments (at least in when I'm calling f).
Additional information: The point is that I want to define different functions f1 and deside before starting the loop, what f is going to be inside of the loop (depending on whatever input).
Pointer arithmetic, in the sense of calculating address offsets from a pointer, is not allowed in Fortran. Pointer arithmetic can easily cause memory errors and the authors of Fortran considered it unnecessary. (One could do it via the back door of interoperability with C.)
Pointers in Fortran are useful for passing procedures as arguments, setting up data structures such as linked lists (e.g., How can I implement a linked list in fortran 2003-2008), etc.