9

How does one access an element of an array that is returned from a function? For example, shape() returns an array of integers. How does one compare an element of that array to an integer? The following does not compile:

integer :: a
integer, dimension(5) :: b

a = 5
if (a .eq. shape(b)) then
    print *, 'equal'
end if

The error is:

if (a .eq. shape(c)) then
    1
Error: IF clause at (1) requires a scalar LOGICAL expression

I understand that this is because shape(c) returns an array. However, accessing an element of the array does not appear to be possible like so: shape(c)(1)

Now if I add these two lines:

integer, dimension(1) :: c
c = shape(b)

...and change the if clause to this:

if (a .eq. c(1)) then

... then it works. But do I really have to declare an extra array variable to hold the return value of shape(), or is there some other way to do it?

1
  • If your array always starts at 1, you could use ubound(b,1). Commented Jul 25, 2013 at 4:42

4 Answers 4

14

Further to the answers that deal with SHAPE and logical expressions etc, the general answer to your question "How does one access an element of an array that is returned from a function?" is

  • you assign the expression that has the function reference to an array variable, and then index that array variable.

  • you use the expression that has the function reference as an actual argument to a procedure that takes a dummy array argument, and does the indexing for you.

Consequently, the general answer to your last questions "But do I really have to declare an extra array variable to hold the return value of shape(), or is there some other way to do it?" is "Yes, you do need to declare another array variable" and hence "No, there is no other way".

(Note that reasonable optimising compilers will avoid the need for any additional memory operations/allocations etc once they have the result of the array function, it's really just a syntax issue.)

The rationale for this particular aspect of language design is sometimes ascribed to a need to avoid syntax ambiguity and confusion for array function results that are of character type (they could potentially be indexed and/or substringed - how do you tell what was intended?). Others think it was done this way just to annoy C programmers.

Sign up to request clarification or add additional context in comments.

1 Comment

This does answer the real question about Fortran style, so I'm accepting this as the answer. However, @SuperCow and @cup both fixed my short-term problem by recommending size or ubound with the dim attribute specified. Thanks to all!
7

Instead of using shape(array), I would use size(array).

Note that this will return an integer indicating how many elements there are in ALL dimensions, unless you specify the DIM attribute, in which case it will return only the number of elements in the specified dimension.

Take a look at the gfortran documentation:

http://gcc.gnu.org/onlinedocs/gfortran/SIZE.html.

Also, look up lbound and ubound.

1 Comment

size and ubound both appear to work great for me when I supply the dim parameter. I appreciate the tips!
2

Note that the expression

a == shape(b) 

returns a rank-1 array of logicals and the if statement requires that the condition reduce to a scalar logical expression. You could reduce the rank-1 array to a scalar like this:

if (all(a == shape(b)))

This is certainly not a general replacement for the syntactically-invalid application of array indexing to an array-returning function such as shape(b)(1).

Comments

1

It is possible even without the intermediate variable using ASSOCIATE:

 real c(3,3)
 associate (x=>shape(c))
   print *,x(1),x(2)
 end associate
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.