Отрицательная индексация массива и размещение в памяти (указание) - PullRequest
2 голосов
/ 15 августа 2011

В Фортране вы можете объявить массив с любым подходящим (целочисленным) диапазоном, например:

real* 8 array(-10:10)

Я считаю, что фортран при передаче по ссылке всегда обходит массив (1) какссылка, но я не уверен.

Я использую указатели фортрана, и я считаю, что фортран указывает на «1-й» адрес элемента, т.е. массив (1), а не массив (-10).Однако я не уверен.

Как Фортран справляется с отрицательной индексацией массива в памяти?И определяется ли имплиментация?

Редактировать: Чтобы добавить немного больше деталей, я передаю блок malloc'd из C в Fortran с помощью указателя Fortune, чтобы указать на адрес, который являетсявыполняется вызовом программы Fortran из CIe C:

void * pointer = malloc(blockSize*sizeof(double));
fortranpoint_(pointer);

И процедура точки Fortran выглядит следующим образом:

real*8 :: target block(5, -6:6, 0:0)
real*8 :: pointer array(:,:,:)

entry fortranPoint(block)
array => block
return

Проблема в том, что иногда, когда она позже пытается получить доступ,:

array(1, -6, 0)

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

Ответы [ 2 ]

1 голос
/ 15 августа 2011

Аргумент массива Fortran ABI зависит от компилятора и, возможно, что более важно, от того, имеет ли вызываемая процедура явный или неявный интерфейс.

Для неявного интерфейса обычно передается адрес первого элемента [1].В вызываемом объекте процедура добавляет смещение в зависимости от того, как объявлен фиктивный аргумент массива.Например, если фиктивный аргумент массива объявлен somearray (-10: 10), тогда ссылка на somearray (x) вычисляется как

address_of_first_element_passed_in_to_the_procedure + x + 10

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

[1] Обратите внимание, что это первый элемент в памяти, то есть самый низкий индекс для каждого измерения.Не somearray (1) независимо от того, как был объявлен массив.

Чтобы ответить на ваш обновленный вопрос, для совместимости C / Fortran, используйте функцию ISO_C_BINDING, которая в настоящее время широко доступна.Это обеспечивает стандартизированный способ передачи информации между C и Fortran.

0 голосов
/ 15 августа 2011

Если фиктивный аргумент для обычного массива в Фортране объявлен A (:) (или с большим количеством измерений), передается SHAPE, а не конкретный диапазон индекса. Таким образом, процедура по умолчанию будет одноиндексной. Вы можете переопределить это с помощью объявления в процедуре A (-10 :) или A (StartIndex :), где StartIndex - другой аргумент.

Указатели Fortran включают диапазон индекса, но механизм передачи будет зависеть от компилятора. Код, взаимодействующий с C, вероятно, зависит от ОС и компилятора. Как уже предлагалось, я бы использовал обычный массив и привязку ISO C. Это НАМНОГО проще, чем старые способы определения механизмов передачи компилятора и стандартные и переносимые. Если у вас большой существующий код на Фортране, вы можете написать «склеивающую» процедуру на Фортране, которая сопоставляет обычные объявления переменных на Фортране и имена привязок ISO C. Хотя их типы будут иметь формально разные имена, на практике они будут одинаковыми, если вы выберете правильные типы ISO C. Привязка ISO C доступна уже много лет. Можете ли вы обновить компилятор на целевой целевой платформе? Если нет, я бы использовал обычный массив Фортрана и либо использовал бы нулевое индексирование на стороне C, либо явно передавал в качестве аргументов нужные индексы.

Существуют примеры использования привязки ISO C к другим вопросам переполнения стека.

Интерфейс для процедуры является явным, если он объявлен так, что он известен компилятору в вызывающей программе. Самый простой способ это разместить процедуры в модуле и «использовать» модуль в вызывающей программе. Наличие явных интерфейсов помогает избежать ошибок, поскольку компилятор может проверять согласованность между аргументами вызывающего и вызываемого. Это немного похоже на заголовочные файлы C, только проще.

...