2013-02-06 35 views
1

編輯:Gfortran 6現在支持這些擴展:)轉換FORTRAN DEC UNION/MAP擴展別的

我有一個廣泛使用工會和地圖進行了一些舊代碼F77。我需要使用不支持這些擴展的gfortran進行編譯。我已經想出瞭如何轉換除這些以外的所有不受支持的擴展,並且我很茫然。我對可能的方法有了幾點想法,但一直沒有能夠成功實施任何事情。我需要以現有的方式訪問現有的UDT;我可以重新實現UDT,但它們的接口一定不能改變。

的我有什麼

例子:

TYPE TEST 
    UNION 
    MAP 
     INTEGER*4 test1 
     INTEGER*4 test2 
    END MAP 
    MAP 
     INTEGER*8 test3 
    END MAP 
    END UNION 
END TYPE 

訪問元素必須以下列方式可供選擇:TEST%爲test1,TEST%TEST2,TEST%TEST3

我的想法thusfar:

  1. 以某種方式替換fortran EQUIVALENCE。
  2. 定義結構中的C/C++,並以某種方式使他們的Fortran代碼可見(懷疑,這是可能的)

我想,一定有很多F77的重構,以F90/95當UNION和MAP被排除在標準之外。如何處理這件事?

編輯:接受的答案有一個解決方法,以允許內存重疊,但至於保留API,這是不可能的。

+0

你真的需要使用gfortran?英特爾Fortran編譯器支持UNION/MAP擴展。其他商業編譯器也可能支持它。 gfortran文件說他們應該支持它,並且如果有人有時間的話可能會得到它。 – WaywiserTundish

回答

3

UNION和MAP從不是任何FORTRAN標準的一部分,它們是供應商擴展。 (例如,參見http://fortranwiki.org/fortran/show/Modernizing+Old+Fortran)。所以他們並沒有被真正排除在Fortran 90/95標準之外。它們導致變量在內存中重疊。如果代碼實際使用此功能,那麼您將需要使用equivalence。在沒有轉換的情況下在不同類型的變量之間移動數據的首選方法是transfer內在的,但對於您而言,您必須識別需要進行轉換的每個位置,而使用equivalence時,它會隱式發生。當然,這會讓代碼變得不那麼容易理解。如果內存疊加僅僅是爲了節省空間,並且不使用變量的等價性,那麼你可以擺脫這個「功能」。如果代碼和你的例子一樣,使用小整數,那麼我猜測正在使用內存覆蓋。如果疊加層是大型數組,則可能已經完成以節省內存。如果這些聲明也創建新類型,則可以使用用戶定義的類型,這些類型絕對是Fortran> = 90的一部分。

如果代碼使用不同類型的變量的內存等價性,則這可能不是可移植的,例如,整數和實數的內部表示可能在代碼最初運行的機器和當前機器之間不同。或者也許變量只是用來存儲位。有很多東西要弄清楚。

P.S.針對評論中的問題,這裏是一個代碼示例。但是......要清楚......我不認爲使用等價是好的編碼實踐。使用gfortran通常用於調試代碼的編譯器選項,gfortran會拒絕此代碼。寬鬆的選擇,gfortran將編譯它。那麼將會如何。

module my_types 

use ISO_FORTRAN_ENV 

type test_p1_type 
    sequence 
    integer (int32) :: int1 
    integer (int32) :: int2 
end type test_p1_type 

type test_p2_type 
    sequence 
    integer (int64) :: int3 
end type test_p2_type 

end module my_types 


program test 

use my_types 

type (test_p1_type) :: test_p1 
type (test_p2_type) :: test_p2 

equivalence (test_p1, test_p2) 

test_p1 % int1 = 2 
test_p1 % int1 = 4 

write (*, *) test_p1 % int1, test_p1 % int2, test_p2 % int3 

end program test 
+0

我排除了trasfer,因爲那需要修改使用這些用戶定義類型的代碼,這是我需要避免的。例如,我無法想出使用等價的方法,將test1和test2的部分聲明爲等同於test3。此外,訪問元素必須以下列方式提供:TEST.test1,TEST.test2,TEST.test3 – Ethereal

+0

我認爲您需要定義兩個單獨的用戶定義類型,一個使用test1&test2,另一個使用test3,然後將它們等同起來。您必須更改代碼中的語法,例如TEST_P1%test1,TEST_P1%test2,TEST_P2%test3。這是付出的代價,因爲原始代碼使用了非標準功能。 –

1

問題是聯合是用於節省空間還是用於替代表示相同的數據。如果你正在移植,看看它是如何使用的。也許,因爲空間有限,它是以變量必須共享的方式編寫的。現在擁有大量的內存,也許這不是必要的,並且可能不需要聯合。在這種情況下,它僅僅是兩種不同類型的