07-Fortran基礎--Fortran指針(Pointer)的使用

07-Fortran基礎--Fortran指針Pointer的使用

  • 0 引言
  • 1 指針(Poionter)的有關內容
    • 1.1 一般類型指針
    • 1.2 數組指針
    • 1.3 派生類(type)指針
    • 1.4 函數指針
  • 2 可運行code


0 引言

??Fortran是一種廣泛使用的編程語言,特別適合科學計算和數值分析。Fortran 90引入了指針的概念,允許程序員動態地管理內存,并在程序中創建靈活的數據結構,前面已經簡單介紹過指針類型的定義和賦值,這一部分詳細講下指針的幾種用法。

1 指針(Poionter)的有關內容

??在Fortran中,指針是一種特殊的變量類型,用于存儲內存地址。指針可以指向任何類型的數據,包括標量、數組、派生類、函數和其他變量。以下是一些Fortran中使用指針的基本概念和用法:

1.1 一般類型指針

??下面運行示例中包含了簡單類型指針使用的差不多😀所有情況,可以仔細閱讀注釋進行理解。

	implicit none! - 1 簡單指針定義real(8),target :: realNum1 = 5.d0, realNum2 = 100.d0real(8),pointer :: ptr real(8),pointer :: ptr2 ! - 1. 簡單的單一變量指針(有以下幾種使用情況)! a 簡單指針賦值print *,"a:簡單指針,ptr獲取了realNum1的地址,此時打印ptr和realNum1是相同值"ptr => realNum1print *,"ptr=",ptr,"realNum1=",realNum1! b 在a的基礎上修改print *,""print *,"b:修改realNum1的值,ptr也發生改變,因為ptr => realNum1,使ptr和realNum1指向同一處內存空間"realNum1 = 55.d0print *,"ptr=",ptr,"realNum1=",realNum1! c 在b基礎上print *,""print *,"c:修改ptr的值,realNum1也發生變量,原因是ptr和realNum1地址一樣"ptr = 60.d0print *,"ptr=",ptr,"realNum1=",realNum1! d 在c的基礎上print *,""print *,"d:修改ptr指向realNum2,發現此時ptr的值和realNum2相同,而realNum1保持c的結果"ptr => realNum2print *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1! e:如果d之后把指針ptr置空 [若要運行將e和f屏蔽]nullify(ptr)print *,""print *,"e:使ptr指向為空,發現打印ptr會報錯; 僅僅ptr的指向噶了,并不影響它指向的空間"if(associated(ptr) == .true.)thenprint *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1elseprint *,"ptr=,Null   ","realNum2=",realNum2,"realNum1=",realNum1endif!! f:如果d之后把指針ptr釋放了(deallocate)!print *,""!print *,"f:執行這一步之前將e先屏蔽,使用deallocate釋放調指針ptr,從輸出結果可以看出,僅僅ptr的指向噶了,并不影響它指向的空間"!deallocate(ptr)!if(associated(ptr) == .true.)then!    print *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1!else!    print *,"ptr=,Null    ","realNum2=",realNum2,"realNum1=",realNum1!endif! g:給指針分配內存print *,""print *,"g:既然可以使用deallocate釋放指針,那當然也可以用allocate分配指針內存了"allocate(ptr2)ptr2 = 200.d0  ! 給指針ptr2賦值print *,"ptr2=",ptr2! h:在g的基礎上print *,""print *,"h:ptr2是指針,被allocate分配過,那是否還有指向的屬性? 指向還是存在的,但這時侯會存在一個問題,	ptr2和realNum1都開辟過空間,而ptr2又指向了realNum1的空間,那就有泄露產生了,因為分配的指針是不會自己釋放內存的;"ptr2 => realNum1print *,"ptr2=",ptr2,"realNum1=",realNum1! i: 在h的基礎上print *,""print *,"i:指針ptr和指針ptr2之間的關系是怎樣的?讓ptr=>ptr2打印結果,發現ptr和ptr2此時指向的為同一空間,值都為realNum1;"ptr=>ptr2 print *,"ptr=",ptr,"ptr2=",ptr2,"realNum1=",realNum1end program

運行結果

1.2 數組指針

??同樣,用示例說明用法,主要介紹了數組指針基礎用法用指針進行數組截斷分析對內存的影響

	implicit none! - 2 指針數組定義integer,allocatable :: ind(:)real(8),target :: arr1(3),arr2(5)real(8),pointer :: p1(:) !> 指針數組 real(8),pointer :: p2(:) !> 指針數組 ! 先給arr1和arr2賦值call RANDOM_SEED()call RANDOM_NUMBER(arr1)arr2 = 5.d0! a:數組指針簡單使用print *,""print *,"a:指針ptr數組簡單使用,二者地址一致打印結果相同,同簡單類型指針類似,p1和arr1任何一個被該,另一個也隨著被改;"p1 => arr1print *,"arr1",arr1,"p1",p1! b:數組指針的特別用法print *,""print *,"b:數組指針可以指向數組中特定索引的元素(a:b),實現拆分數組,指針可以多次指向同一目標, 指向的空間/內存必須是連續的;"p1 => arr1(2:3)print *,"arr1",arr1,"p1",p1! c:分配內存print *,""print *,"c:可以使用allocate進行內存分配,分配和指向不沖突"allocate(p1(6))p1 = 6print *,"arr1",arr1,"p1",p1! d:數組指針釋放print *,""print *,"c:可以使用allocate進行內存分配,分配和指向不沖突"deallocate(p1)if( associated(p1) == .true. )thenprint *,"p1未成功釋放"elseprint *,"p1已釋放"endifend program

運行結果

1.3 派生類(type)指針

??同樣,用示例說明用法,主要介紹了派生類指針的基礎用法和賦值

	program testimplicit none! - 3 派生類指針定義type :: test_type  !> 定義派生類real(8) :: arr(100000)real(8) :: arr2(200000)real(8),pointer :: ptr3 end typetype(test_type),target :: typeValuetype(test_type),pointer :: ptype ! 定義派生類指針! -3. 派生類中指針使用較為常見,因為派生類中可能會同時存在多個大數組,對內存是致命傷害! - a:派生指針的賦值ptype => typeValue            ! 先給指針指向目標,此時二者表示同一內存區域call RANDOM_NUMBER(ptype%arr) ! 給派生數組賦值ptype%ptr3 =>realNum1         ! 給指針的指針賦值print *print *,"派生類指針初始化"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",ptype%arr(1),"    派生類指針的指針",ptype%ptr3! - b:指針ptype內存釋放?print *deallocate(ptype)print *,"釋放指針ptype,不影響派生變量typeValue前面的賦值"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",typeValue%arr(1),"    派生類指針的指針",typeValue%ptr3! -c:派生類指針內存分配 print *allocate(ptype)call RANDOM_NUMBER(ptype%arr) ! 指針賦值ptype%ptr3 =>realNum1print *,"指針ptype分配內存,賦初值"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",ptype%arr(1),"    派生類指針的指針",ptype%ptr3print *,"對于這樣的派生類,使用指針是最高效、最省內存的了"end program

運行結果

1.4 函數指針

??同樣,用示例說明用法,主要介紹了調用函數指針計算將函數指針作為參數在函數之間傳遞

program testimplicit none! - 4 函數指針    procedure(f), pointer :: pfreal(8) :: fv,x! -4. 函數指針的使用! a: 函數指針的簡單使用print *print *, "函數指針的簡單使用"pf => fprint *, 'pf(2) = ', pf(2.d0) ! 調用f(2.)pf => gprint *, 'pf(2) = ', pf(2.d0) ! 調用g(2.)print *! b: 函數指針可以作為變量進行傳值pf => fx = 100.d0call calfun(pf,x,fv)write( *,*),"函數指針作為參數的運算結果",fvcontainsreal function f(x)real(8), intent(in) :: xf = x**2end function freal function g(x)real(8), intent(in) :: xg = x**3end function gsubroutine calfun(fun,x,fv)procedure(f),pointer :: funreal(8),intent(in) :: xreal(8),intent(out) :: fvfv = fun(x)end subroutineend program 

2 可運行code

program test_pointerimplicit none! - 1 簡單指針定義real(8),target :: realNum1 = 5.d0, realNum2 = 100.d0real(8),pointer :: ptr real(8),pointer :: ptr2 ! - 2 指針數組定義integer,allocatable :: ind(:)real(8),target :: arr1(3),arr2(5)real(8),pointer :: p1(:) !> 指針數組 real(8),pointer :: p2(:) !> 指針數組 ! - 3 派生類指針定義type :: test_type  !> 定義派生類real(8) :: arr(100000)real(8) :: arr2(200000)real(8),pointer :: ptr3 end typetype(test_type),target :: typeValuetype(test_type),pointer :: ptype ! 定義派生類指針! - 4 函數指針    procedure(f), pointer :: pfreal(8) :: fv,xptr2 => null() ! 指針指向空! - 1. 簡單的單一變量指針(有以下幾種使用情況)! a 簡單指針賦值print *,"a:簡單指針,ptr獲取了realNum1的地址,此時打印ptr和realNum1是相同值"ptr => realNum1print *,"ptr=",ptr,"realNum1=",realNum1! b 在a的基礎上修改print *,""print *,"b:修改realNum1的值,ptr也發生改變,因為ptr => realNum1,使ptr和realNum1指向同一處內存空間"realNum1 = 55.d0print *,"ptr=",ptr,"realNum1=",realNum1! c 在b基礎上print *,""print *,"c:修改ptr的值,realNum1也發生變量,原因是ptr和realNum1地址一樣"ptr = 60.d0print *,"ptr=",ptr,"realNum1=",realNum1! d 在c的基礎上print *,""print *,"d:修改ptr指向realNum2,發現此時ptr的值和realNum2相同,而realNum1保持c的結果"ptr => realNum2print *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1!! e:如果d之后把指針ptr置空!nullify(ptr)!print *,""!print *,"e:使ptr指向為空,發現打印ptr會報錯,僅僅ptr的指向噶了,并不影響它指向的空間"!if(associated(ptr) == .true.)then!    print *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1!else!    print *,"ptr=,Null   ","realNum2=",realNum2,"realNum1=",realNum1!endif!!! f:如果d之后把指針ptr釋放了(deallocate)!print *,""!print *,"f:執行這一步之前將e先屏蔽,使用deallocate釋放調指針ptr,從輸出結果可以看出,僅僅ptr的指向噶了,并不影響它指向的空間"!deallocate(ptr)!if(associated(ptr) == .true.)then!    print *,"ptr=",ptr,"realNum2=",realNum2,"realNum1=",realNum1!else!    print *,"ptr=,Null    ","realNum2=",realNum2,"realNum1=",realNum1!endif! g:給指針分配內存print *,""print *,"g:既然可以使用deallocate釋放指針,那當然也可以分配指針"allocate(ptr2)ptr2 = 200.d0  ! 給指針ptr2賦值print *,"ptr2=",ptr2! h:在g的基礎上print *,""print *,"h:ptr2是指針,被allocate分配過,那是否還有指向的屬性? 指向還是存在的,但這時侯會存在一個問題,&ptr2和realNum1都開辟過空間,而ptr2又指向了realNum1的空間,那就有泄露產生了,因為分配的指針是不會自己釋放內存的;"ptr2 => realNum1print *,"ptr2=",ptr2,"realNum1=",realNum1! i: 在h的基礎上print *,""print *,"i:指針ptr和指針ptr2之間的關系是怎樣的?讓ptr=>ptr2打印結果,發現ptr和ptr2此時指向的為同一空間,值都為realNum1;"ptr=>ptr2 print *,"ptr=",ptr,"ptr2=",ptr2,"realNum1=",realNum1! -2. 指針數組的使用! 先給arr1和arr2賦值call RANDOM_SEED()call RANDOM_NUMBER(arr1)arr2 = 5.d0! a:數組指針簡單使用print *,""print *,"a:指針ptr數組簡單使用,二者地址一致打印結果相同,同簡單類型指針類似,p1和arr1任何一個被該,另一個也隨著被改;"p1 => arr1print *,"arr1",arr1,"p1",p1! b:數組指針的特別用法print *,""print *,"b:數組指針可以指向數組中特定索引的元素(a:b),實現拆分數組,指針可以多次指向同一目標, 指向的空間/內存必須是連續的;"p1 => arr1(2:3)print *,"arr1",arr1,"p1",p1! c:分配內存print *,""print *,"c:可以使用allocate進行內存分配,分配和指向不沖突"allocate(p1(6))p1 = 6print *,"arr1",arr1,"p1",p1! d:數組指針釋放print *,""print *,"c:可以使用allocate進行內存分配,分配和指向不沖突"deallocate(p1)if( associated(p1) == .true. )thenprint *,"p1未成功釋放"elseprint *,"p1已釋放"endif! -3. 派生類中指針使用較為常見,因為派生類中可能會同時存在多個大數組,對內存是致命傷害! - a:派生指針的賦值ptype => typeValue            ! 先給指針指向目標,此時二者表示同一內存區域call RANDOM_NUMBER(ptype%arr) ! 給派生數組賦值ptype%ptr3 =>realNum1         ! 給指針的指針賦值print *print *,"派生類指針初始化"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",ptype%arr(1),"    派生類指針的指針",ptype%ptr3! - b:指針ptype內存釋放?print *deallocate(ptype)print *,"釋放指針ptype,不影響派生變量typeValue前面的賦值"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",typeValue%arr(1),"    派生類指針的指針",typeValue%ptr3! -c:派生類指針內存分配 print *allocate(ptype)call RANDOM_NUMBER(ptype%arr) ! 指針賦值ptype%ptr3 =>realNum1print *,"指針ptype分配內存,賦初值"write(*,"(a,f10.6,a,f10.6)"),"派生類指針下數組",ptype%arr(1),"    派生類指針的指針",ptype%ptr3print *,"對于這樣的派生類,使用指針是最高效、最省內存的了"! -4. 函數指針的使用! a: 函數指針的簡單使用print *print *, "函數指針的簡單使用"pf => fprint *, 'pf(2) = ', pf(2.d0) ! 調用f(2.)pf => gprint *, 'pf(2) = ', pf(2.d0) ! 調用g(2.)print *! b: 函數指針可以作為變量進行傳值pf => fx = 100.d0call calfun(pf,x,fv)write( *,*),"函數指針作為參數的運算結果",fvcontainsreal function f(x)real(8), intent(in) :: xf = x**2end function freal function g(x)real(8), intent(in) :: xg = x**3end function gsubroutine calfun(fun,x,fv)procedure(f),pointer :: funreal(8),intent(in) :: xreal(8),intent(out) :: fvfv = fun(x)end subroutineend program 

??程序中若有不理解的地方可以留言討論,希望對需要的人有些許幫助。

🕝
🕝🕝
🕝🕝🕝
🕝🕝🕝🕝
🕝🕝🕝🕝🕝
🕝🕝🕝🕝🕝🕝
🕝🕝🕝🕝🕝🕝🕝

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12942.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java代碼混淆工具ProGuard混淆插件

java代碼混淆工具ProGuard混淆插件 介紹 ProGuard是一個純java編寫的混淆工具,有客戶端跟jar包兩種使用方式。可以將程序打包為jar,然后用工具進行混淆,也可以在maven中導入ProGuard的插件,對代碼進行混淆。 大家都知道 java代…

【華為OD機試-C卷D卷-200分】田忌賽馬(C++/Java/Python)

【華為OD機試】-(A卷+B卷+C卷+D卷)-2024真題合集目錄 【華為OD機試】-(C卷+D卷)-2024最新真題目錄 題目描述 給定兩個只包含數字的數組a,b,調整數組 a 里面的數字的順序,使得盡可能多的a[i] > b[i]。 數組a和b中的數字各不相同。 輸出所有可以達到最優結果的a數組的…

SadTalker 自定義容器化部署配置

Docker 環境檢查 執行docker info 查看環境種是否有安裝docker,否則首先安裝好docker 運行環境。在線環境安裝執行執行兩條指令即可 sudo apt install docker sudo apt-get install docker-ce sudo apt-get install docker-composesudo systemctl restart dockerG…

langchain源碼

itemgetter:返回一個函數,函數取輸入dict的某個指定key Runnable 的基本方法有 invoke、 batch、 await、 ainvoke、 abatch 同步轉異步 Runnable 還具有的方法:bind、 with_config。 input_schema 屬性、output_schema 屬性 with_retry方…

Uniapp H5開發常見問題解析

引言 在移動應用開發領域,Uniapp已經成為一個備受矚目的技術框架,其跨平臺能力和高效開發特性使得開發者能夠更加便捷地構建出功能豐富、性能優越的應用程序。特別是在H5開發中,Uniapp的應用場景日益廣泛,然而,隨之而…

Vue2之使用provide和inject實現兩個不相干組件之間的通信

Vue2之使用provide和inject實現兩個不相干組件之間的通信 文章目錄 Vue2之使用provide和inject實現兩個不相干組件之間的通信1. 祖先組件中使用provide提供數據2.后代組件A中使用inject注入并使用數據3.后代組件B中使用inject注入并使用數據 在Vue 2中以使用provide和inject來實…

[ciscn 2022 東北賽區]math

1.題目 import gmpy2 from Crypto.Util.number import * from flag import flag assert flag.startswith(b"flag{") assert flag.endswith(b"}") messagebytes_to_long(flag) def keygen(nbit, dbit):if 2*dbit < nbit:while True:a1 getRandomNBitIn…

編輯器目錄樹的設計,一點也不簡單

朋友們好&#xff0c;我是優秀的大鵬 今天花了很長時間思考一個網頁文檔編輯器&#xff0c;云端目錄樹要怎么設計 這個看似簡單的需求&#xff0c;技術上和產品上的思考卻非常復雜 下面以幾種編輯器為例&#xff0c;講一下各種編輯器在技術上和產品的思考 1、以Vscode為代表的本…

Delphi DataSet轉JSon (使用SuperObject)

Delphi中將TDataSet轉換為JSon字符串。 with ATM.LoadDataSet() dobeginif IsEmpty thenbeginLogObj.WriteLog(未查詢到該視圖名稱下該時間段內的上傳數據&#xff0c;視圖名稱&#xff1a; AViewname 開始時間&#xff1a; AStartdate 結束時間&#xff1a; AEnddate);exit…

【神經網絡與深度學習】Transformer原理

transformer ENCODER 輸入部分 對拆分后的語句x [batch_size, seq_len]進行以下操作 Embedding 將離散的輸入&#xff08;如單詞索引或其他類別特征&#xff09;轉換為稠密的實數向量&#xff0c;以便可以在神經網絡中使用。位置編碼 與RNN相比&#xff0c;RNN是一個字一個字…

Django Rest Framework 全局異常處理

在Django Rest Framework&#xff08;DRF&#xff09;中&#xff0c;全局異常處理是一種重要的機制&#xff0c;它可以幫助我們更好地管理API中的異常情況&#xff0c;并返回統一的錯誤響應。本文將詳細介紹兩種全局異常處理的方法&#xff1a;使用中間件&#xff08;Middlewar…

機器學習(3)

目錄 3-1線性回歸 3-2最小二乘解 3-3多元線性回歸 3-4廣義線性模型 3-5對率回歸 3-6對率回歸求解 3-7線性判別分析 3-8LDA的多類推廣 3-9多分類學習基本思路 3-10類別不平衡 3-1線性回歸 線性模型為什么重要&#xff1f; 人類在考慮問題時&#xff0c;通常…

用python寫一個自動生成android開機動畫的工具

要創建一個自動生成Android開機動畫的工具&#xff0c;你需要一些基本的知識&#xff0c;比如Python編程、圖像處理和Android開機動畫的格式。以下是一個簡單的Python腳本示例&#xff0c;它可以生成一個基本的Android開機動畫&#xff0c;具體效果可能需要更多的調整和優化。 …

記錄glide加載圖片,設置圓角

支持所有角的圓角&#xff0c;自動計算合適的半徑&#xff0c;不用擔心圖片比預定值小導致的圓角過大的問題 修改自&#xff1a;https://blog.csdn.net/qq_15059163/article/details/97613790 增加了指定圖片尺寸、解決了圖片某些情況下圓角過大的問題 public class GlideRou…

先有JVM還是先有垃圾回收器?很多人弄混淆了

是先有垃圾回收器再有JVM呢&#xff0c;還是先有JVM再有垃圾回收器呢&#xff1f;或者是先有垃圾回收再有JVM呢&#xff1f;歷史上還真是垃圾回收更早面世&#xff0c;垃圾回收最早起源于1960年誕生的LISP語言&#xff0c;Java只是支持垃圾回收的其中一種。下面我們就來刨析刨析…

外賣系統的JWT實現登錄

1、什么是JWT jwt可以生成一個加密的token&#xff0c;作為用戶登錄的令牌&#xff0c;當用戶登陸成功之后&#xff0c;發放給客戶端。請求需要登錄的資源或者接口的時候&#xff0c;將token攜帶&#xff0c;后端驗證token是否合法。jwt有三部分組成&#xff1a; A&#xff1a;…

【特大喜訊】國內前33位持有PMI-RMP風險管理專業認證的學員分享~!

【學員背景】 沈陽某信息科技有限公司&#xff0c;從事企業采購供應鏈數字化轉型方向&#xff1b; 為企業提供有效的降本增效解決方案。 【學員順利拿證后期訪問】 問&#xff1a;學員您好&#xff0c;首先恭喜您順利拿到RMP證書&#xff0c;請問您在此次備考過程中&#xf…

抖店商品詳情API接口(產品參數|詳情圖)

抖店商品詳情API接口(產品參數|詳情圖) 參數僅供參考&#xff1a; {"code": 0,"msg": "調用成功","time": "1715763239","data": {"properties": [{"format": [{"message": [{&q…

C語言簡要(一)

總得讓她開心吧 helloworld #include <stdio.h>int main() {printf("hello world!\n");return 0; } 程序框架 #include <stdio.h> int main {return 0; }輸出 printf("hello world!\n"); "里面的內容叫做“字符串”&#xff0c;prin…

BUUCTF靶場[MISC]wireshark、被嗅探的流量、神秘龍卷風、另一個世界

[misc]wireshark 考點&#xff1a;流量、追蹤流 工具&#xff1a;wireshark 先看題目&#xff0c;管理員密碼 將下載的文件用wireshark打開&#xff0c;查找flag 點擊追蹤tcp流&#xff0c;開始挨個查看flag [misc]被嗅探的流量 考點&#xff1a;流量、追蹤流 工具&#xf…