?

淺談C語言中數組變量的教學

2020-03-08 06:02周二強
現代計算機 2020年36期
關鍵詞:數組表達式指針

周二強

(河南城建學院計算機與數據科學學院,平頂山467036)

數組是C語言教學中的重點和難點,本文提出虛擬變量的概念,直觀而深刻地揭示數組變量的本質。把數組統一為變量,為學生自主理解辨析數組和指針變量鋪平了道路,也為反轉教學提供必要的條件,極大地提高學生的學習積極性。

虛擬變量;數組;指針;C語言

圖1 相關變量的存儲狀態簡圖

0 引言

C語言是經典的結構化程序設計語言,其語法被現代編程語言廣泛借鑒,國內許多高校都開設了C語言課程。國內現行C語言教材大多強調實訓,注重編程能力的培養,忽視了C語言和計算機的關系,導致C語言教材中的一些概念不清,既不利于學生系統分析能力的培養,也不便于反轉課堂等教學改革的進行。近年來新出現的“反轉”課堂(Flipped Class,也譯為“翻轉”課堂)教學模式,引起了教育界的廣泛關注?!胺崔D”即師生互換角色,教師是主導,學生是主體,這充分發揮了以人為本的教學思想和教師的主導作用[1]。在課堂教學活動中應強調學生的參與意識,充分體現學生在課堂中的主體地位[2]。

數組是C語言教學中的重點。使用數組可以方便地重復處理大量的數據,作為數據結構,數組的基本用法不難掌握。但由于現行教材對數組概念的模糊處理,使得多數學生不能自主學習有關知識點,更不要說積極主動地參與反轉課堂了,導致學習效果不理想,不會利用指針變量操作復雜的數組。

1 變量、指針變量和數組變量

在C語言中,借助變量使用計算機中的存儲單元,一個變量標識了計算機中的一塊存儲單元。存儲單元是內存塊在C語言中的抽象,具有固定的大小,分類型,某類存儲單元只能存放該類數據。

語句int i;定義了一個整型(int)變量i,它對應于一個整型(int)存儲單元,只能存儲一個整數(int)。語句int*pi;定義一個整型指針變量pi,它對應于一個整型指針(int*)存儲單元,只能存儲一個整型存儲單元的地址(int*)。與普通變量存儲常見的數據不同,指針變量用于存儲地址。地址是存儲單元在計算機中的編號,用于定位存儲單元。

語句i=5;可以把整數5存入與變量i相關的存儲單元中。語句pi=&i;可以把與變量i相關的整型存儲單元的地址存入與變量pi相關的存儲單元中,此時常形象地稱指針變量pi指向了變量i。它們在內存中的狀態可用圖1簡單地表示。

可簡單地認為,變量i的值是5,指針變量pi的值是&i。由于地址屬于計算機的內部數據,而非用戶數據,故對初學者而言,指針變量難以理解。指針變量的用法分兩步,首先,以直接引用的方式使用指針變量本身,如pi=&i;,使得指針變量指向變量i;然后,以間接引用的方式借助指針變量使用其指向的變量,如*pi=6;。盡管直接引用的方式簡便,但受變量作用域的限制。只要獲得了存儲單元的地址就能以間接引用的方式使用存儲單元,間接引用的方式可以擴展存儲單元的使用范圍[3]。

語句int a[3]={1,2,3};定義一個數組變量a,即申請了一塊存儲單元用于存儲整數1,2,3。數組變量a由3個整型變量組成,其內存狀態可能如圖2所示。

圖2 數組a的內存狀態

由圖2可知,數組變量a沒有專屬于自己的存儲單元,并不是一個真正的變量,數組變量a的值是C語言規定的。從這個角度分析,數組變量a是一個符號常量。但sizeof(a)的值是12,即數組變量a的存儲單元有12個字節,數組元素的存儲單元都屬于數組變量a,所以,不能簡單地把數組變量a理解為普通的符號常量。數組a應理解成一個虛擬的變量[3]。數組變量a指向了其首元素,數組變量a與其首元素a[0]的關系可用圖3表示。

圖3 虛擬的數組變量a

數組變量a是一個int[3]型存儲單元。由圖3可知,其地址和值均為0x0012ff00,但這兩個地址的意義不同,其地址(&a)是一個int[3]型地址,其值(a)是一個int地址(&a[0]),即&a+1指向下一個int[3]型存儲單元,其值為0x0012ff12,但a+1指向a[1],其值為0x0012ff04。

2 二維數組變量

以二維數組int a[3][2]={{1,2},{21,22},{31,32}}為例,它的內存狀態可能如圖4(1)所示。

圖4 二維數組a的內存狀態

二維數組a有3個數組元素a[0]、a[1]和a[2],數組元素的類型是長度為2的一維整型數組,即它們標識一個int[2]型存儲單元。

二維數組變量a是一個虛擬的變量,它標識的存儲單元的長度為24個字節(sizeof(a)的值為24),類型為int[3][2]。二維數組變量a也指向了首元素a[0],其值為int[2]型地址0x0012 ff00,*a與a[0]可以互換使用,sizeof(*a)與sizeof(a[0])的值為8。

一維數組a[0]所標識的存儲單元長度為8個字節,類型為int[2]。一維數組變量a[0]指向了首元素a[0][0],其值為int型地址0x0012 ff00,*a[0]與a[0][0]可互換使用,sizeof(*a[0])或sizeof(a[0][0])的值為4。

二維數組變量a,一維數組變量a[0],整型變量a[0][0]三者的關系如圖4(2)所示。

如有int*p,則指針變量p不能用二維數組a賦值,因為二維數組變量a的首元素a[0]為int[2]型,即長度為2的一維整型數組,而指針變量p只能存儲int型地址??梢源鎯nt[2]型地址的指針變量理想的定義方式為int[2]*p,而C語言中實際的定義方式為int(*p)[2]。定義了可以指向int[2]型存儲單元的指針變量p后,就可以用p=a(或p=&a[0])讓指針變量p指向數組a的首元素a[0]了。此時指針變量p、二維數組變量a、一維數組變量a[0]及a[0][0]的關系如圖5所示。

圖5 二維數組與指向其首元素的指針變量

3 舉例分析二維數組與指針變量

下面程序用三種方式輸出了二維數組a的數組元素。

分析:

p=a;執行后,指針變量p也指向了數組a的首元素a[0],故p+i指向了a[i],*(p+i)與a[i]標識了同一個長度為2的一維整型數組,表達式(*(p+i))[j]標識了該數組型存儲單元的第j個數組元素,表達式(*(p+i))[j]與a[i][j]可互換。

pi=a[i];執行后,pi也指向了a[i]的首元素a[i][0],故pi+j指向了a[i][j],因此表達式*(pi+j)與a[i][j]標識同一個整型存儲單元。

pi=a[0];執行后,pi也指向了a[0]的首元素a[0][0]。表達式*pi++求值時,兩個操作符優先級相同,右結合,先計算子表達式pi++,值為pi,原表達式的值為*pi,但求值的同時,變量pi的值自增1,pi指向了與原指向的存儲單元相鄰的下一個同類型存儲單元。第一次求值時,表達式*pi++與a[0][0]標識了同一個存儲單元,且pi指向了a[0][1];第二次求值時,表達式*pi++與a[0][1]標識了同一個存儲單元,且pi指向了a[0][2];……。由于數組的數組元素相鄰,故通過重復地輸出表達式*pi++的值也可以輸出數組a的所有數組元素。

4 結語

指針的使用,極大地提高了C語言的執行效率,但地址的存在,增加了C語言的學習難度。給初學者提供一個直觀且準確的概念,不僅可以極大地降低學習難度,不會造成C語言知識點的殘缺,而且也為啟發式教學提供了可能,教學效果顯著。

猜你喜歡
數組表達式指針
JAVA稀疏矩陣算法
JAVA玩轉數學之二維數組排序
靈活選用二次函數表達式
郊游
更高效用好 Excel的數組公式
為什么表的指針都按照順時針方向轉動
尋找勾股數組的歷程
淺析C語言指針
議C語言中循環語句
怎樣確定一次函數表達式
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合