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