奚:王老師,指針是C語言中最難掌握的概念了吧?
王:是呀,學生對C語言的畏懼幾乎都來自對指針的畏懼。但是指針同時也是功能非常強大而且應用非常廣泛的,因此遲早都必須掌握它[1]。
奚:其他高級語言不包含指針嗎?
王:包含,但是大多數高級語言根本就不允許你對指針進行任何操作,你只能看一看指針指向哪里[2]。
奚:你們選擇C和C++來研究程序語言發展規律,是否與它們包含了對指針的操作有關?
王:可以這樣說。指針為C語言編程提供了強大的支持——如果能正確而靈活地利用指針,就可以直接切入問題的核心,或者將程序分割成一個個片段。一個很好地利用了指針的程序會非常高效、簡潔和精致[2]。學好指針也是為通用的數據結構和具體的標準模板庫的學習做準備[1],因為C++的STL迭代器的機制是模擬指針的操作而設計[3],迭代器是指針的高級形式。事實上,指針是數據和處理的中介:計算機處理的數據需要存儲,數據存儲是為了處理,處理一般通過指針找到存儲中的數據。程序語言的發展都會反映在指針的發展上。
奚:指針這么重要,卻一直令人生畏,問題在哪里呢?
王:主要在教學環節上。很多教材都是簡單地把指針等同于地址,而實際上,地址和指針的關系,是低級機器語言中的地址和高級C語言中的指針的關系,是語言要素從低級到高級的發展。按照辯證法指南,我們只有切實地研究這個發展過程,才能真正認識指針本身。
奚:那么,指針和地址的關系應該如何描述呢?
王:它們是辯證法意義上的否定關系。“一切發展,不管其內容如何,都可以看作一系列不同的發展階段,它們以一個否定另一個的方式彼此聯系著”[4]。而且每一種事物都有它的特殊的否定方式,經過這樣的否定,它同時就獲得發展,每一種觀念和概念也是如此 [5]。如果不研究指針否定對地址的特殊的否定方式,即不研究從地址到指針的發展,指針就會神秘化,就會成為教條,就會與人對立起來,使人對它的認識只能停留在本能地服從或熟悉它的使用約定上。有一本引進的《標準C++寶典》就這樣說:“毫無疑問,數組和指針讓剛剛接觸C和C++的程序員感到頭痛。這時,最好堅持反復練習一些最基本的使用約定,直到習慣了指針和數組之間的可互換性,概念上的模糊就會越來越少”[6]。甚至還說,“對于初學C和C++的程序員而言,指針、地址以及指針和數組之間的關系都是非常令人頭痛的概念。現在我教給大家一個好辦法,把下面這些例子掛在計算機上方的墻上,每天注視它們,直到對指針和地址的運用已經成為一種本能”[7]。
奚:這不是把指針和地址的關系當成一種死記硬背的公式了嗎?
王:就是啊。不分析事物的變化、發展,不研究事物矛盾的特殊性,有關的一切理論、概念都會成為框框、教條。
奚:這種方法可能還具有一定的代表性吧?
王:是的,但辯證唯物主義要求我們,理論不應該是教條,而應該是對包含著一連串互相銜接的階段的那種發展過程的闡明[8]。對于指針、地址以及指針和數組之間的關系,應該結合程序設計,結合機器語言和C語言這兩個被地址和指針銜接起來的程序語言階段來認識。
奚:在學習C語言之前,計算機專業的學生可能專門學過機器語言,而非計算機專業的學生可能就沒有學過機器語言。要打破專業界限地學習C語言,機器語言這一章應該包含多少內容才合理呢?
王:對專門學過機器語言的學生,這一章是按照程序語言發展規律所做的概括和總結。對沒有學過的學生,這一章包含了程序語言的一切要素和這些要素進一步發展的可能。比如地址發展為指針的可能。
奚:這種可能是怎么實現的呢?
王:地址發展為指針,是因為程序語言向前發展了;程序語言向前發展了,是因為數據處理即程序設計的需要向前發展了。因此,我們只有從程序設計的需要出發,才能闡明從地址到指針的發展。“指針、地址以及指針和數組之間的關系”之所以令人頭痛,是因為程序設計對指針的需要還沒有獲得合乎規律、合乎邏輯的表達,還沒有成為指針定義的一部分。
奚:怎樣才能做到合乎規律、合乎邏輯呢?
王:機器語言發展到C語言,作為機器語言要素的地址就要發展為C語言的要素,這就是指針類型。指針是C的類型,就應該和整型、字符型等語言內置類型一樣,具有自己的常量,因此,指針字面值常量的引入是不可避免的。而處理的需要又使指針一但出現就和數組構成一個整體,它們都以對方的存在作為自己存在的前提。這種整體性要求把一個變量等價于一個長度為1的數組,把指向一個變量的指針看作是指向一個長度為1的數組的指針。這種整體性的科學性需要二維指針和二維數組的定義來檢驗,例如,二維數組必須是一維數組的推廣,就像二重積分是一重積分的推廣一樣,而且它們在一定條件下可以互相轉化。這一切就是合乎規律、合乎邏輯的。
奚:這樣說來,指針和數組是相互依賴、相互作用的關系。
王:是的,相互作用是事物真正的終極原因。我們不可能追究到比相互作用更深層的原因,因為在它背后沒有什么可認識的了[9]。
奚:既然指針和數組是辯證的關系,那么我們可以把這種關系包含在指針和數組的定義中,這樣就不再令我們頭痛了。
王:應該這樣的。形而上學在認識事物的時候,忽視了它們的聯系,而辯證法是在普遍聯系中認識事物。
奚:您文章中的圖3和表1分別是關于一維數組和二維數組的整體特征的表述,其中具體列出了很多元素之間的關系。數組是什么,是否就綜合在這張表中。
王:是的。“具體之所以具體,因為它是許多規定的綜合,因而是多樣性的統一”[10]。例如,對資本主義經濟形態中的人口,馬克思有一段精彩的論述:“拋開構成人口的階級,人口就是一個抽象。如果我不知道這些階級所依據的因素,如雇傭勞動、資本等等,階級又是一句空話。而這些因素是以交換、分工、價格等等為前提的。比如資本,如果沒有雇傭勞動、價值、貨幣、價格等等,它就什么也不是”[10]。經過馬克思的分析和綜合,人口已不是一個混沌的關于整體的表象,而是一個具有許多規定和關系的豐富的總體了[10]。
奚:辯證法真是處處顯示出它高屋建瓴的作用。
王:這就是辯證思維的結果。
奚:這種方法應該是中學生進入大學之后盡快掌握的方法。
王:是的。“分析和綜合不是一種辯證的認識方法,而是基本的辯證的認識方法,其他認識方法都是這個方法的環節、方面或表現。因為分析和綜合的過程,就是矛盾的分析與綜合的過程,就是對立統一規律在認識過程中的完整表現和運用,就是辯證的認識過程的橫剖面”[11]。
奚:您的文章在敘述指針和數組的性質時,處處包含人的需要,例如,“超過下標范圍的索引訪問是非法的,不管編譯器對超越下標范圍的訪問如何處理,我們都要自覺的遵守這個實際上是屬于我們自己的設計”。還有,“如果傳遞數組指針的目的是傳遞數組的值,那么應該把數組指針傳遞給同類型指針變量”。我覺得這些表達很有“以人為本”的味道。
王:這也是合乎規律、合乎邏輯的表達。地址發展為指針,歸根到底是數據處理即程序設計的需要向前發展了,而進行數據處理的是人,數據處理的需要是人的需要。“實踐就是具有必然性和普遍性的主觀要求的實現”[12]。可以說,我們對指針的需要在多大程度上被合乎規律、合乎邏輯地表達出來,我們就在多大程度上認識了指針。
奚:如您上一期所說,辯證邏輯要求我們“必須把人的全部實踐——作為真理的標準,也作為事物同人所需要它的那一點聯系的實際確定者——包括到事物的完美的‘定義’中去”。于是,概念的定義包含著實踐,實踐包含著人的需要。
王:“凡是把理論引向神秘主義方面去的神秘東西,都能在人的實踐中以及對這個實踐的理解中得到合理的解決”[13]。
奚:在您引用的《標準C++寶典》的一段話中,提到反復練習,能不能說這也是實踐呢?
王:實踐活動,不管內容如何,都是沿著一系列從低級到高級的階段發展的。練習是反復學習,以求熟練。而學習的知識和理論是實踐活動的概括和總結,應該說練習也是實踐。但是概括和總結的方法不同,練習的意義和效果也就不同。例如,舊形而上學是從那種把非生物和生物當作既成事物來研究的自然科學中產生的[14],囿于當時實踐的局限性,它看待事物的方法是孤立、靜止和片面的。而馬克思主義唯物辯證法是以十九世紀中葉的細胞學說、能量守恒與轉化定律和達爾文的進化論等自然科學的巨大進步為基礎的。
奚:所以辯證法的概括和總結是最進步、最重要的思維方法。
王:不僅如此,現代自然科學每天都提供大量材料,證明自然界的一切歸根到底都是辯證的,而不是形而上學的,形而上學的方法已經是不中用的了。例如,當物理學進入亞原子世界,物質離開它們同周圍環境的相互作用關系,我們就無從描述。像“夸克”這樣的物質,到現在為止我們甚至還不知道它能否單獨存在。
奚:所以辯證法認為,事物是普遍聯系的,沒有孤立存在的事物。
王:當我們試圖為亞原子畫像時,采用的儀器裝置不同,結果不同,觀察者和觀察對象成了不可分割的整體。
奚:所以辯證法要求把人的實踐包含到關于事物的完美定義中去。
王:如果我們能夠自覺地做一個辯證唯物主義者,而不是等到自然界中處處存在的辯證性質迫使我們接受辯證法,我們就會少走很多彎路。如果指針和數組一開始就以相互依存、相互作用的關系出現,如果地址和指針能夠從程序設計的需要出發,被合乎規律、合乎邏輯地表達出來,指針、地址以及指針和數組之間的關系就不會如書上所說非常令我們頭痛,我們也就不需要“每天注視它們,直到對指針和地址的運用已經成為一種本能”。
奚:我們的練習、我們的學習就會是主動的、積極的。
王:是的,因為在實踐中,人是主動的、積極的。
參考文獻
[1](美)William J.Collins著. 周翔譯. Data Structures and the Standard Template Library(數據結構與STL)[M].北京:機械工業出版社,2004. 27.
[2](美) Paul S.R.Chisholm等著. 張芳妮,呂波譯. C語言編程常見問題解答[M].北京:清華大學出版社,2000.112.
[3](美)Mark Allen Weiss著.張懷勇等譯. Data Structures and Algorithm Analysis in C++ Third Edition(數據結構與算法分析C++描述(第3版))[M].北京:人民郵電出版社,2007.62.
[4]《馬克思恩格斯全集》(第4卷)[M].北京:人民出版社.,1972.329.
[5]《馬克思和恩格斯選集》(第4卷)[M].北京:人民出版社,1995.223.
[6](美)AI Stevens,Clayton Walnum著.林麗閔,別紅霞等譯.Standard C++ Bible(標準C++寶典)[M].北京:電子工業出版社,2001.154.
[7](美)AI Stevens,Clayton Walnum著.林麗閔,別紅霞等譯.Standard C++ Bible(標準C++寶典)[M].北京:電子工業出版社,2001.147.
[8]《馬克思和恩格斯選集》(第4卷)[M].北京:人民出版社,1972. 459.
[9]《馬克思和恩格斯選集》(第3卷)[M].北京:人民出版社,1972. 55.
[10]《馬克思和恩格斯選集》(第2卷)[M].北京:人民出版社,1995.18.
[11] 黃楠森著.《<哲學筆記>與辯證法》[M].北京:北京出版社,1984.70-71.
[12] 黃楠森著.《<哲學筆記>與辯證法》[M].北京:北京出版社,1984. 235.
[13]《馬克思和恩格斯選集》(第1卷)[M].北京:人民出版社,1995.56.
[14]《馬克思和恩格斯選集》(第4卷)[M].北京:人民出版社,1995.245.