Размер массива после освобождения

#fortran #intel-fortran

#массивы #фортран #размер

Вопрос:

Я создал распределяемый массив. Я выделяю элементы, а затем печатаю размер массива. Я нахожу странным, что размер остается неизменным после освобождения.

   Integer, Allocatable :: fred(:)
  Allocate (fred(3))
  Write (*,*) "fred: ", Size (fred)
  Deallocate (fred)
  Write (*,*) "fred: ", Size (fred)
 

Комментарии:

1. Это недопустимый код Fortran: любой результат, который вы получаете, разрешен для процессора Fortran.

2. О чем ты говоришь?

3. Я ответил, но на самом деле меня интересует, каким, по вашему мнению, будет правильный результат.

4. @Zeus он имеет в виду, что если ваш код не соответствует стандарту, то он недействителен для Fortran. Если код выходит за рамки стандарта, то нет ничего, что определяло бы, что означает «правильное» поведение, а это означает, что любое поведение является правильным. См. Концепцию «неопределенного поведения» на языке Си. Фортран не использует этот термин, но концепции применимы.

5. @Zeus загрузите копию стандарта и ознакомьтесь с ним. В частности, посмотрите на Fortran 2008 Cl. 13.7.156 параграф 3. It shall not be an unallocated allocatable variable ссылаясь на аргумент SIZE .

Ответ №1:

На самом деле это вопрос, требующий канонического ответа. В интересах ответа на ваш конкретный вопрос в отсутствие (насколько я могу судить, но я могу написать его в конце концов), я отвечу.

Аргумент to size не должен быть нераспределенной распределяемой переменной.

Для вашего кода fred это выделяемая переменная. Если этот блок кода выполняется, то в последней строке size есть аргумент, который является нераспределенной распределяемой переменной. В этом случае, если он является частью программы (программный модуль), то эта программа (программный модуль) не является стандартной соответствующей программой (программный модуль).

Это несоответствие не является несоответствием, которое процессор Fortran должен обнаружить, чтобы быть соответствующим процессору Fortran.

Да, было бы неплохо, чтобы процессор обнаружил это, и многие это сделают, если вы выберете соответствующие параметры во время компиляции. Процессору, соответствующему стандарту, будет разрешено, говоря популярным языком, начать Третью мировую войну в ответ на этот код. Он также может печатать 3 . Это полностью зависит от прихоти поставщика компилятора.

Подсказанный комментариями, дополнительная информация.

Возможно, заманчиво ожидать, что размер освобожденного массива равен нулю. Однако освобожденный массив и массив с нулевыми элементами — это совершенно разные вещи, так же как символ нулевой длины — это не то же самое, что нераспределенный выделяемый символ.

В частности, у нас есть такие идиомы, как

 fred = [fred, append]
 

которые недопустимы, когда fred не выделяются, но являются допустимыми, когда они выделены, но имеют нулевой размер; и в этом последнем случае он не нуждается в специальной обработке.

Я согласен с комментарием High Performance Mark о том, что, если компилятор собирается возвращать какое-либо значение, 0 это плохой выбор. Поскольку размер не определен четко, любая попытка доступа fred(3) , скажем, на основе возвращаемого размера, также является плохой идеей. Опять же, компилятор может предоставить любое конкретное значение для этой ссылки.

Наконец, если вы хотите проверить, выделен ли массив, вам следует использовать allocated встроенное значение, а не полагаться на size возврат 0 . Конечно, в этом случае это не нужно, так как вы можете быть совершенно уверены, что after deallocate оператор fred действительно не выделен.

В Fortran 90 статус выделения мог быть неопределенным, а затем даже allocated не был разрешен.


Те же идеи применимы для вещей, отличных от массивов и size встроенных. size это функция запроса, которая требует, чтобы массив, о котором запрашивается, был выделен (если выделяемый объект) или связанный указатель (если указатель). Равным образом, например, символ с отложенной длиной должен быть выделен / связан с указателем (если применимо), чтобы быть аргументом len встроенной функции запроса.

Функции запроса не всегда требуют выделения / связывания аргументов. Например, может быть запрошена длина символа явной длины, даже если переменная не выделена. Следует проверять требования в документации и не делать запросы, которые не разрешены.

Комментарии:

1. Вы всегда можете проверить с Allocated (fred помощью)

2. Я использую выделенный для проверки, однако, когда программа вызывает процедуру удаления, я хочу показать ему, что доступных данных нет, поэтому я показываю значение 0. Затем он может заполнить его нужными данными.

3. Возможно, был неявный вопрос, который я не заметил (я склонен не замечать никакого контекста из вопроса — это моя вина). Если вы можете более четко объяснить, чего вы хотите, я еще раз попытаюсь ответить. Однако, по сути, нераспределенный массив должен (компилятором и программистом) обрабатываться совершенно иначе, чем выделенный массив размером 0.

4. Все в порядке. Знание того, что компилятор имеет размер с неопределенным статусом для нераспределенных переменных, ответило на мой вопрос.