唯识与C语言指针

旧文虽无殊胜处却最解少年意,重发于此,乃自喜其披坚执锐行而无返之气。

作者按

丙申孟春,始得熊君十力之微言宏旨,于《新唯识论》中得窥心外无物,体用不二,翕辟成变之理。数年兵、道、史、释之学,终为一脉贯通,于世间纷杂,万相罗织,始有定见。乃身蹈统摄之道,心得自在清凉,不免情动于衷,喜不自胜。

熊君为阐唯识之旨,于书中多举譬喻。举“海水与众沤”喻,“绳索与大麻”喻种种;更尝作图形,以穷其本旨,表其胜义,苦口婆心,令人动容,非沐手开卷不能彰其功,焚香斋戒不能铭其德。吾观乎此学,虽能以物物强为譬喻,然万物浩汤,皆为大化,果有以大化喻大化之理乎?终须另觅一人造之物,探幽寻明,见微知著,庶几可得于大化矣。今请试以指针喻之。

下面开始正常说话。

这是要干什么?

没有人会对“世界到底是什么?”这个问题不感兴趣。科学、哲学、艺术,宗教都在以种种的方式诠释这个问题的答案。作为人生不可逃避的问题之一,每个人或多或少,也都会有自己或明朗或隐约的勾画。

但是在这个问题上,一直存在诸多的争论。且不说唯心唯物之争,在以确定性立身的科学领域,在人们得窥量子的堂奥之后,也观察到了诸如“二相性”、“测不准”,“非定域”等等的现象,虽然有各个理论都在尝试自圆其说,但不可否认的一点是,随着人类的进步,世界不是变得越来越简单,而是变得越来越复杂了。

而这恰恰是符合逻辑的。外物确为实有,却不曾脱离心而存在。人类的进步,自然伴随心智的成长,自然就会见到以前“视而不见”的东西。并非有新物凭空而生,而是原物之一“相”得显于成长了的心智。这一新“相”又成为心智继续成长的养料,从而使人认识到更多。这一过程永无休止,方生方死,方死方生。这不是简单的唯物或唯心,而是要结合两者各自的主张。

唯识论就是在做这一尝试。为表明物与心的关系,亦即如何认识世界的问题,熊君在其论述中做了种种譬喻。惜哉熊君,英才天纵,所举例证却仅限于瓶、罐、桌,绳之间,虽可强为譬喻,但恐有志于学者,不能于此中得其全旨。

计算机是人类创造的一个世界,人通过编程语言与这个世界发生相互作用。正可成为我们用以阐明世界本旨的绝佳实例。简单类比,计算机里的三极管,是真实存在的“物”,三极管的开关,是其呈现出的“相”,而对这些开关如何认识,就是我们的“心”。唯识精深,非我所能穷究,仅在此以C语言另作一譬喻,以望有启于同侪,足慰心愿。

如何从C语言中领悟心外无物

在Linux上编写的C语言是相对底层的语言,原因有很多,但可以直接操作允许范围内的系统内存一定是原因之一。内存的操作除了分配、释放和更改之外,还需要更加频繁地标记和指向,这便引入了指针的概念。一个指针也只是一个普通的变量,只是它的值是一个内存的地址,如此便“指向”了该内存。这些基础的知识,无需再赘言。本文所强调的,是指针、内存、程序之间的种种变换。

有如下基础代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*object struct*/

struct object

{

element_type element;

...

};

/*void pointer*/

void*ptr=NULL;

struct object obj;

obj.element=element_value1;

/*point to obj, cast to type struct object*/

(struct object*)ptr=&obj;

/*modify obj's member value through pointer*/

*ptr.element=element_value2;

Line1-6 声明object结构体

Line 8 定义了一个指针,类型为void*,并指向NULL

Line 9 定义了objecti结构体对象obji,系统为其分配一片内存

Line 10 为iobj中的elementi成员赋值为element_value1

Line 12 将对象iobji所在的内存首地址存入iptri指针中,并将指针类型转换为struct object *

Line 14 解析ptri指针,更改ielement对应内存的内容,并赋值为ielement_value2

定义对象obj,系统在栈内存上划出了一片内存空间,其长度为obj的长度。但在完成这一步之后,这一部分内存并没有因此产生任何变化。内存里的每一个比特,并没有带上任何“这是obj的内存”的标记。从内存本身来看与没有obj时没有分别。内存作为载体,是一切变动的肇始,不增不减,不净不垢,是真实存在的。

物是实有的

到这里,分配给obj的这片内存是有实体存在,却是没有任何“相”可言的。

在Line10中,我们为elementi赋值,相应的,会引起内存的变化。变化的内存的位置,程序可于struct objecti的定义中得知(计算element_type的offest,)。在赋值之后,这片内存有了第一个“相”,我们可以将这个“相”笼统称为“element的值为element_value1”的obj,就如同我们称呼一个“蓝色带横条纹的“皮球一样。这个值,可以为任何一个允许的值,于是obj就可以显现出任何一个对应的“相”。

相是变动不居的

接下来是对指针的的操作。指针是什么?前面虽然已有技术上的说明,但还没有点出本文想阐明的主旨。指针可以让程序连接到相应的数据内存上,如果将程序本身比作自身的意识,内存比作实有的物质世界,那么指针就是我们用以认识世界的感官,是“眼耳鼻舌身意”,它将决定我们接触(看、听、嗅,触摸等等)到哪个实有的物质(指向内存),以及意识中对物质的“相”如何认识(依何种struct定义去解析内存)。

真正的关键,是指针类型的转换。只有将指针的类型转换为struct object *i,后续的代码才有意义。类型转换并没有改变指针本身,它所在的内存地址,它的长度,它的作用域等等并没有任何变化,但程序(意识)却懂得了,它所接触到的那片内存(实体),是一个struct object的区域(相),并且可以以此认识和改造obj此时显现出来的“相”。这便是常说的“相由心生”之意。

人通过感官与物质的相发生作用

就像我们的眼睛、口鼻,手足(指针本身)始终没有什么变化,但我们却可以将某一物质识为瓶瓶罐罐,桌子麻绳,皆是因为我们的意识通过感官注意于其上(Line12),并依照指针的类型给出了对此“相”解释。依照对“相”的理解,我们可以作用于物质,令起变为另外一种“相”(Line14)。

如果我们不能通过感官去注意(动宾用法,下同)此物,或对此物视而不见(即不能有相关的struct去解释此物,”视而不见”不等同于”看不到”),那么虽然该物是真实存在的,但其“相”在我们的心里是不存在的。此柏拉图洞穴壁影所喻之意,亦为王阳明“与花同归于寂,同起于明”之意。就像虽然内存中的数据是一直都有的,但如果我们没有指针类型的转换,甚至没有struct object的定义,那对程序(意识)来说,任何obj的“相”都是不存在的。唯其二者(指针与struct)皆备于心(意识),才可得obj之“相”。此所谓“心外无物”之意。

如何从C语言中领悟翕辟成变

一个某一类型的指针,只要该类型(struct)存在于程序(意识)中,就可以内存(实有的物质)作出相应的解析(物质的相)。通过对“相”的认识(struct中成员的定义),就可以使意识与物质发生作用,但所能改变的,及其改变后的形态,却始终不出“相”的范畴。若上述明了,可稍悟叔本华“意志与表象”之旨。

但我们需注意的是,指针的类型可以变为任意类型。如从ivoid*变为istruct object*i,其指向的内存并没有变化,内存本身也没有变化,但程序(意识)对这片内存的解释发生了变化。同一物质,转换成了另外的相,这便是熊君所述,物质转为心上之相的翕的势用。

如指针从struct object*类型转为void*i类型,则对程序而言,该处内存所显现出的相尽皆消失,只是一片混沌虚静,原有的“相”复返归于大化,此熊君所述,心上之相转为物质的辟的势用。翕辟两者结合,便是老子所谓“无为而无不为”之意。

从中亦说明一个道理,同一个物质,可计现万相。即同一片内存,可以接受任何类型的指针,其所显现的“相”,亦因指针类型的不同而可显为一组群相。而某一时刻我们所见得的一种”相“,只是此实在之物的“诈现”之相。“相”终是变动不居的,此即《心经》所述“一切有为法,皆如梦幻泡影,如电亦如露”之意。

于万相中取其一相

有如下基本代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct object1{intobject1_num;};

struct object2{intobject2_num;};

void*ptr=NULL;

struct object1 obj;

(struct object1*)ptr=&obj;

/*assign random_value to the first sizeof(int) bytes*/

*ptr.object1_num=random_value;

/*cast pointer type to struct object* and do the same thing*/

*(struct object2*)ptr.object2_num=randome_value;

/*cast pointer type to int* and do the same thing*/

*(int*)ptr=random_value;

/*cast pointer type to char* and do the same thing*/

int i=sizeof(int);

while(--i){

*(char*)(ptr+i)=random_value&(0xFF000000>>(i*8));

}

以上的代码,从Line12开始,都是在对同一块内存进行相同的赋值操作。不同的指针类型,使程序对同一块内存的解释也不尽相同。struct可以从iobject1object2乃至于无穷,所有的struct皆可为&obj处内存所诈现的任一之相。这也解释了,为什么同一事物,有人识得,却有人不识,或两人皆识得,却有不同的态度和看法。

人的一生,始终都在填充自己的头文件库。有了新的阅历,即是添加了新的struct;对事物有了新的认识,即是在原有的struct中添加了新的成员变量。意识将这些从感官搜集来的struct再重新注意于感官(指针类型转换)之上,便得出了我们所见的世界。

如果我们所见到的事物,只是真实本体诈现的一相,我们是否有可能穷尽事物所有的相?答案是不能。因为我们的感官无法无限拓展。虽然我们如今有了红外探测仪,X光机等等设备辅助我们的眼睛,声呐、雷达等设备辅助我们的耳朵,但即便是集合所有的外来辅助,甚至是未来所有的外来辅助,所能见到的也只是物质本体的一部分“相”。如一个红色的气球,在可见光范围内,红色是其一相,在红外线范围内,又呈另外一相,既有物质波的相,也有引力波的相,未来还会有新的相。这个过程,便是人对物质的逐步深入认识,即寻找出本体所呈现出的更多的相。但这永远不会止步,就如同struct的定义没有限制一样。所能得知的,就是在指针类型的转换中,在一翕一辟中,在对struct不断地添加调整修改中,形成了我们现在所身处的此在世界。就如同指针不能指向地址长度之外的内存一样,有些相,是我们永远也看不见的。但这些看不见的东西,离我们并不遥远,它是与我们能见到的“相”同时存在的,都是实有的物质本身。如同引力波是物质都具有的一个“相”,但在之前我们都不曾有所体认一样。我们始终在认识“相”的路上,而成就了一切“相”却又不是“相”的,是实有的物质。此即老子所谓“万物恃之以生而不辞,功成不名有,衣养万物而不为主”之谓。

再论人生之意义

如果我们无法完全识却世界之本体万相,那我们岂非是活在自欺欺人之中。此言大谬。须知当指针指向一片内存的时候,程序便已可接触内存的每一位比特。易言之,当感官接收到某一实体显现的“相”时,意识已经注意到了实体本身。套用不同的struct会让同一片内存显为不同的“相”,但并不妨碍程序在此“相”中对内存的操作和功用。人生的意义,须在这里求得。

每一段程序,都有其特别的作用,即便是运行在同一台机器上,运行在同一片内存上(不同时刻),也都有其所特有的对内存的理解和操作。为完成程序自身的任务,体现其意义与价值,每段程序都要对内存有其自身的理解与互动。我们见不到实体全部的“相”,并不是对我们的一种限制,恰恰是对我们的一种褒奖。让我们可以于万相纷杂中取其一,并专注于此,完善自己的心智,完成自己的任务。

而人生的意义,不在于求得对实体的全部理解,因为那可能是别人的人生,是一种向外的追寻;真正的意义在于求得自身的圆满,而这一切都需要向内去寻求。写好自己的头文件,磨练自己的API,若能将自己这段“程序”补充完整,让它完成自己要去做的任务,吾不知复有何求矣。

2016.4.22

© 2020 DecodeZ All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero