2016-05-25 2 views
1

В Fortran, вы можете изменить массивы с указателями:Fortran указатели массива на скаляр

program working 

    implicit none 

    integer, dimension(:,:), pointer :: ptr 
    integer, dimension(6), target :: trg 

    trg = (/1,2,3,4,5,6/) 
    ptr(1:2,1:3) => trg 

    ! Here, you can use the 6-sized 1D array trg 
    ! or the 2 by 3-sized 2D array ptr at the same time. 
    ! Both have the same content (6 integers), but are only indexed 
    ! differently. 

    write(*,*) ptr(1,2) 

end program working 

Эта программа пишет «3», который в соответствии с правилами перекроить.

Аналогичным образом, я попытался сделать то же самое, но не с 1D до 2D, а от 0D до 1D.

program not_working 

    implicit none 

    integer, dimension(:), pointer :: ptr 
    integer, target :: trg 

    trg = 1 
    ptr(1:1) => trg 

    ! I hoped to be able to use the scalar trg at the same time as 
    ! the one-sized 1D array ptr. I thought they both have the same 
    ! content, but are only indexed differently. 

    write(*,*) ptr(1) 

end program not_working 

Ожидалось увидеть «1». Но он не компилируется.

Gfortran 4,9 говорит:

Error: Rank remapping target must be rank 1 or simply contiguous at (1)

Ifort 14.0.2 говорит:

<file>.f90: catastrophic error: Internal compiler error: segmentation violation signal raised Please report this error along with the circumstances in which it occurred in a Software Problem Report. Note: File and line given may not be explicit cause of this error. compilation aborted for <file>.f90 (code 1)

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

+0

Использовать тег [tag: fortran] и при необходимости добавьте другой тег для конкретной версии (не здесь). Фактически вы используете функцию Fortran 2003. –

+0

'Внутренняя ошибка компилятора' ** всегда ** ошибка в компиляторе. Это может быть вызвано неправильным кодом, но всегда это ошибка в компиляторе. Компилятор не должен терпеть крах, даже если вы поставляете неправильный код. В нем также четко сказано, что вы должны делать * «Просьба сообщить об этой ошибке вместе с обстоятельствами, в которых это произошло в отчете о проблеме с программным обеспечением». * Вы сделали это? –

+0

Обратите внимание, что версия Intel версии 14 немного устарела, и вы должны подумать об обновлении. –

ответ

0

Скаляр - это не просто непрерывный массив, потому что он не является массивом. Это так просто. Gfortran обнаруживает это и жалуется, ifort запутан и сбой. Но ваш код недействителен, вы не можете указать указатель массива на скаляр.

0

Указатели массива предназначены для указания массивов, поэтому не могут указывать на скаляры (вместо этого мы можем использовать скалярные указатели для этой цели). Но если мы определенно хотим использовать указатели массива, чтобы указать на скаляры (по некоторым причинам), мы могли бы использовать c_f_pointer() такие, что

use iso_c_binding 

integer, target :: a 
integer, pointer :: p(:), q(:,:), r(:,:,:) 

a = 777 

call c_f_pointer(c_loc(a), p, [1]) 
call c_f_pointer(c_loc(a), q, [1,1]) 
call c_f_pointer(c_loc(a), r, [1,1,1]) 

print *, "p = ", p(:),  "with shape", shape(p) 
print *, "q = ", q(:,:), "with shape", shape(q) 
print *, "r = ", r(:,:,:), "with shape", shape(r) 

Но это явно «небезопасная» особенность (в том смысле, что она позволяет получить доступ к сырец память), и если они используются с неправильными аргументами, то это может дать неправильный результат (или даже катастрофы), например:

call c_f_pointer(c_loc(a), p, [3]) 

print *, "p = ", p(:) !! gives "p = 777 202 0" etc with garbage data 

Итак, если есть какая-то особая причина, я думаю, что это, вероятно, лучше (безопаснее) для использования скалярных указателей для скалярных переменных ...

Смежные вопросы