免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: wwwsq
打印 上一主题 下一主题

531,继续抽某昏昏 [复制链接]

论坛徽章:
0
181 [报告]
发表于 2012-09-26 12:37 |只看该作者
回复 179# starwing83

你这个图还是有点问题的,没有量词;又隐含了顺序:从上到下才正确。
标识符是表达式,更确切地说是它能被规约为表达式中的一种;而显然不是所有的表达式都“是”标识符。
而且你这比喻也有问题。标识符是表达式,标识符集合包含于表达式集合;但名字不是族谱,族谱可以看作是名字和名字之间关系的集合,名字属于族谱。
所以180L说的有理。
另外,你这图里也没写清楚表达式和变量的关系。你的推理中允许表达式和变量相提并论无非是在特定的上下文中改变“表达式”的外延(反正我觉得这种曲线救国的口味不好),并没有其它的逻辑手段。
一般来说,具体的集合名词之间说“A是B”,A和B的外延相等即可;而要在抽象名词之间普遍地说“是”,是需要内涵一致的,因为有时(就像你现在改变了“表达式”指代的情况)难以确定不同讨论者之间抽象名词的外延,于是鸡同鸭讲。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
182 [报告]
发表于 2012-09-26 13:36 |只看该作者
回复 180# wwwsq


    我懂你的意思了,我的意思是identifier和expression都是符号,而variable和eval是符号的外延,从这方面讲是平级的。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
183 [报告]
发表于 2012-09-26 13:44 |只看该作者
回复 181# 幻の上帝


    问题是,一个词说出来,他肯定是有两个含义的:词本身,和词的外延。

通常我们指的是外延,如果没有歧义(大家都指外延),这样的平级应该是允许的“变量(求值)是表达式(求值)的一部分”。如果这种外延有歧义(表达式表示形式语法,还是指表达式求值的过程?),那么这么说是不行的,如果在一个上下文里表达式指形式语法,这时根本就没有变量存在,说变量是有问题的,除非承认变量名是变量的一部分,这就是你觉得味道不对的地方,因为你觉得变量名不是变量的一部分(不是他的属性)。而如果在一个指求值过程的上下文里(a = 1;赋值语句,将1赋值给a),那么这里提到的表达式显然不可能是形式语法,而只可能是这个求值过程,这时说变量是表达式(变量参与表达式计算)是没有问题的。

另一个问题是,如果说变量参与表达式计算,那么能不能说变量是表达式?这两种说法是不是等价?我的理解是,变量本身是求值的(很多动态语言都很明显地能表达这一点),这里变量是表达式,实际上的含义是变量(求值)是表达式(求值),如果上下文隐含了求值这个环境,那么说“是”和说“参与”是等价的——这种求值是个树状的类似集合包含的过程(对a求值是对a = 1求值的一部分),变量求值归根结底是一个主表达式(a)的求值,在这个前提下,变量的确就“是”表达式,这个“是”本身已经不仅仅是参与了,而的确是is-a关系——具体含义是,变量求值的确就是主表达式求值。

如果这个前提条件讲清楚了,那么说变量是表达式,是没问题的。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
184 [报告]
发表于 2012-09-26 14:01 |只看该作者
总结一下看法:

1. 能不能笼统地说变量?
答案是不行,C的形式语法根本没有变量这种东西存在,entity和identifier是分离的。这给予了C很灵活的实现方式。有entity,有identifier,但是你不能说有变量,既然根本就没有变量,那么提到变量明星是不对的。

2. 能不能笼统地说表达式?
这里有几个问题。第一,表达式是个递归概念,有很多种表达式,确切的说identifier仅仅是primary expression而已。表达式实际上在不同上下文有两个含义,这两个含义都在谭书上出现过:指代C的语法(比如谭书上面的一些诸如 if(表达式) 语句 这样的语法说明),或者指代求值过程(谭书上也出现过解释a == 1 || a == 2的求值方式的描述),这两者出现的表达式的说法是不能混淆的。一指表达式本身的结构,运算符、优先级、结合性等等,我很赞同pmerofc的说法是,优先级结合性只是“选取”操作数的优先级而已,和执行顺序计算顺序没有半毛钱的关系,而谭书就有所混淆(不止谭书,伴侣对这点都混淆得很厉害);二指表达式的求值方式,在这一点上就是动真格地要说明计算顺序了,而这是建立在优先级结合性选择操作数的基础上的。而对实在的计算顺序,就得考虑顺序点,然后说明这是实现相关的,而谭书完全没有提到这一点,哪怕开口闭口C99的第四版也是这样。既然要讲明白,就必须说明说指的表达式究竟是哪个情况,是可以算优先级结合性的形式语法,还是算顺序点算短路运算的执行方式,这一点谭书是没有指明的。

3. 能不能说变量是表达式?
同上,既然谭书没有说明表达式的两种含义,这个问题就只能是糊里糊涂了。在形式语法中,根本就是不存在变量这种东西的,所以也谈不上变量是表达式。其次,在形式语法之上实际求值之下,有一个中间层次,即所谓的词法作用域原则,这一点谭书是一带而过,没有细讲。在这两点都不求甚解的情况下,的确说变量是表达式是一笔糊涂账。如果说确立了这两点,讲明白了表达式是求值的那个表达式(外延),同时说明了词法作用域原则,指明了究竟是哪个变量,那么在讲解求值的上下文之中,是可以说变量(求值)是表达式(求值)的。除此以外,就是一笔糊涂账了。

那么,为什么谭书会有这种模糊的地方呢?

如果看过谭浩强的《BASIC程序设计》,大概就能理解了。BASIC语言不是编译语言,而且其表达式就只有求值含义。因为表达式本身就是用来求值的。BASIC也不讲identifier,只讲variable(这一点可以看Lua语法简要,Lua也只讲variable,不讲identifier,基本上解释型语言都是这样的),因此在ASIC里面的确可以说变量是表达式的一部分,所以谭书就就着以前的规则开始算糊涂账了。我们要明白这是因为谭浩强没有确切明白C语言独特的地方,而不是所谓“别有深意”。明白这一点,就对谭书的学术水平有了一个清晰的认识了。

总归来说,老谭是就着一门没有形式语法的语言入门的,那么他写《C程序设计》时闭口不讲形式,就很好理解了。

论坛徽章:
0
185 [报告]
发表于 2012-09-26 15:20 |只看该作者
回复 183# starwing83

如果在一个上下文里表达式指形式语法,这时根本就没有变量存在,说变量是有问题的,除非承认变量名是变量的一部分,这就是你觉得味道不对的地方

对。变量和变量名的存在性是分离的。
因为你觉得变量名不是变量的一部分(不是他的属性)。

不对。我的确觉得变量名不是变量的一部分,但这不和变量名是变量的关联的属性有矛盾。
如果我谈论一个变量,那么与之关联变量名的作用就是保证存在性——保证可以引用到这个变量,但我不关心变量名具体是什么。
如果我谈论一个变量名,我就强调了它和其它引用途径的区别。
后者不代替前者。
而如果在一个指求值过程的上下文里(a = 1;赋值语句,将1赋值给a),那么这里提到的表达式显然不可能是形式语法,而只可能是这个求值过程,这时说变量是表达式(变量参与表达式计算)是没有问题的。

表达式的求值可以简称为求值,不能简称为表达式。
如果只是需要讨论计算,那么我就直接讨论变量和计算的关联,表达式整体的语义,而不关心表达式的形式是什么。(当然,之前要确定表达式是否合乎语法,表达式中的每个成分的语义。)

而且这还是改变不了承认“变量是表达式”需要多增加需要根据上下文约定的前提,也不会说明承认前提之后会有多少方便(不是有更清楚的说法么)。奥卡姆剃刀就把这个前提给去掉了。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
186 [报告]
发表于 2012-09-26 15:40 |只看该作者
回复 185# 幻の上帝


    好,基本达到共识了。

那么也就是说,这个说法在某种前提下是有道理的,只是不够好,对吧?有这个结果我就满意了。

但是我依然不认为表达式求值能简称求值,而不是简称表达式。当然这是个口味问题了。

如果说,变量是求值,这个味道是很奇怪的,变量参与求值,这个倒是正常一点。变量参与表达式求值/变量求值是表达式求值的一部分,这么说不是最好么?

论坛徽章:
0
187 [报告]
发表于 2012-09-26 15:42 |只看该作者
回复 184# starwing83

1. 能不能笼统地说变量?
答案是不行,C的形式语法根本没有变量这种东西存在,entity和identifier是分离的。这给予了C很灵活的实现方式。有entity,有identifier,但是你不能说有变量,既然根本就没有变量,那么提到变量明星是不对的。

对C来说,正确。
不过,假设因为种种理由要在讨论C时添加这么个“变量”的概念,如何定义它就成了问题。

2. 能不能笼统地说表达式?
这里有几个问题。第一,表达式是个递归概念,有很多种表达式,确切的说identifier仅仅是primary expression而已。表达式实际上在不同上下文有两个含义,这两个含义都在谭书上出现过:指代C的语法(比如谭书上面的一些诸如 if(表达式) 语句 这样的语法说明),或者指代求值过程(谭书上也出现过解释a == 1 || a == 2的求值方式的描述),这两者出现的表达式的说法是不能混淆的。一指表达式本身的结构,运算符、优先级、结合性等等,我很赞同pmerofc的说法是,优先级结合性只是“选取”操作数的优先级而已,和执行顺序计算顺序没有半毛钱的关系,而谭书就有所混淆(不止谭书,伴侣对这点都混淆得很厉害);二指表达式的求值方式,在这一点上就是动真格地要说明计算顺序了,而这是建立在优先级结合性选择操作数的基础上的。而对实在的计算顺序,就得考虑顺序点,然后说明这是实现相关的,而谭书完全没有提到这一点,哪怕开口闭口C99的第四版也是这样。既然要讲明白,就必须说明说指的表达式究竟是哪个情况,是可以算优先级结合性的形式语法,还是算顺序点算短路运算的执行方式,这一点谭书是没有指明的。

严格地说,对“表达式”应该只使用第一种意义。上面说过“表达式的求值”可以简作“求值”而非“表达式”。注意这个偏正短语的中心词。
关于优先级,我也赞同pmerofc的说法。片面用优先级替换语法构造容易造成认识误区;没提及求值并妄想用表达式的构造来代替求值语义和行为则是大错。
3. 能不能说变量是表达式?
同上,既然谭书没有说明表达式的两种含义,这个问题就只能是糊里糊涂了。在形式语法中,根本就是不存在变量这种东西的,所以也谈不上变量是表达式。其次,在形式语法之上实际求值之下,有一个中间层次,即所谓的词法作用域原则,这一点谭书是一带而过,没有细讲。在这两点都不求甚解的情况下,的确说变量是表达式是一笔糊涂账。如果说确立了这两点,讲明白了表达式是求值的那个表达式(外延),同时说明了词法作用域原则,指明了究竟是哪个变量,那么在讲解求值的上下文之中,是可以说变量(求值)是表达式(求值)的。除此以外,就是一笔糊涂账了。

这是有问题的。求值只针对表达式。变量实体除了保存值,在此没有更多直接的关联。所以无所谓“变量(求值)”,变量出现的意义最多就是明确存在求值的结果,而和求值的过程无关。

PS.说一个变量是左值云云,其实也只是不严格的习惯性说法。按通常的认知(如果需要引入“变量”这个概念),C的变量和声明引入的对象对应,而对应的标识符/对象名/变量名作为表达式是左值,这点确
切无疑,所以这一层的意义是明确的。但这也不是变量和表达式相提并论的依据;实用时我也只会使用“变量名是左值表达式”这种严格无误的说法代替之(如果有必要引入“变量”的概念)。

那么,为什么谭书会有这种模糊的地方呢?

如果看过谭浩强的《BASIC程序设计》,大概就能理解了。BASIC语言不是编译语言,而且其表达式就只有求值含义。因为表达式本身就是用来求值的。BASIC也不讲identifier,只讲variable(这一点可以看Lua语法简要,Lua也只讲variable,不讲identifier,基本上解释型语言都是这样的),因此在ASIC里面的确可以说变量是表达式的一部分,所以谭书就就着以前的规则开始算糊涂账了。我们要明白这是因为谭浩强没有确切明白C语言独特的地方,而不是所谓“别有深意”。明白这一点,就对谭书的学术水平有了一个清晰的认识了。

总归来说,老谭是就着一门没有形式语法的语言入门的,那么他写《C程序设计》时闭口不讲形式,就很好理解了。


同意。
描述语法的文本本身没有向用户强调区分语法和语义的差异,用户没有顾及,只是盲目遵从习惯,于是就有误区。
我很怀疑老谭学的时候就根本没兴趣去管语法形式是什么,只看怎么用的。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
188 [报告]
发表于 2012-09-26 15:56 |只看该作者
幻の上帝 发表于 2012-09-26 15:42
这是有问题的。求值只针对表达式。变量实体除了保存值,在此没有更多直接的关联。所以无所谓“变量(求值)”,变量出现的意义最多就是明确存在求值的结果,而和求值的过程无关。

PS.说一个变量是左值云云,其实也只是不严格的习惯性说法。按通常的认知(如果需要引入“变量”这个概念),C的变量和声明引入的对象对应,而对应的标识符/对象名/变量名作为表达式是左值,这点确
切无疑,所以这一层的意义是明确的。但这也不是变量和表达式相提并论的依据;实用时我也只会使用“变量名是左值表达式”这种严格无误的说法代替之(如果有必要引入“变量”的概念)。


这里我得说一下,我们理解上有偏差。我觉得不是这样的。因为我是基本上从动态语言(python/ruby/lisp)身上理解语法形式的,所以一开始我就把value和variable分得很清楚(动态语言里面value和variable毫无关系,variable除了指向某个value以外别无用处。本质上variable就是某个数组元素或者某个哈希表项而已,本身不会包含value)。所以我在思考的时候,着重会注重一个概念“字面量”。在我认为,字面量、变量等等都是必须要**求值**的,他们的求值结果就是他们包含的值本身。这就是主表达式形式的外延含义。比如说"abc"你认为它仅仅包含一个匿名字符串字面量。是的,但是我认为如果它出现在表达式中,在求值过程中它本身被求值,没有副作用,求值类型是char*,求值结果是一个指向"abc"的指针,同时这个指针虽然是char*,但是语义限定其只读。我的意思是,我们不能说“变量只存值,在表达式求值中他们唯一做的事情是贡献出自己的值”,不是的,这里有更深的一个层次,应该是“变量包含值,在表达式求值中,变量名作为的主表达式本身也是一个表达式,它也会被求值,它求值的结果是就是这个变量名对应的变量所包含的值,它求值出的类型就是这个变量名对应变量的类型”。这么说才是完整的,而且这个前提和这个层次是无法被剃刀掉的,因为只有这样才能保存C的表达式系统概念上的完整性。

如果有动态语言基础,就可以很清晰地分清楚value,eval和variable。比如Python:
a = 1
a = a + 1
这句话是什么含义呢?第一句,a这个指针指向一个value,value的内容是int类型的1,第二句话的含义是,首先求值表达式a+1,然后让a指向这个求到的新值。注意这里值和a完全没关系,a仅仅具有一个“指向”和“重指向”的作用而已。虽然大多数动态语言会做优化,将int这种值保存在a所占的槽里,但是至少Python3不是这样,integer实实在在地是另外分配的不可变对象,而a仅仅是个指针而已。在这个前提下,a += 1和a = a + 1其实没有任何区别,并没有一个静态语言里面的“累加”含义。

论坛徽章:
0
189 [报告]
发表于 2012-09-26 16:52 |只看该作者
starwing83 发表于 2012-09-26 14:01

[quote]
我觉得不是这样的。因为我是基本上从动态语言(python/ruby/lisp)身上理解语法形式的,所以一开始我就把value和variable分得很清楚(动态语言里面value和variable毫无关系,variable除了指向某个value以外别无用处。本质上variable就是某个数组元素或者某个哈希表项而已,本身不会包含value)。
这里我得说一下,我们理解上有偏差。我觉得不是这样的。因为我是基本上从动态语言(python/ruby/lisp)身上理解语法形式的,所以一开始我就把value和variable分得很清楚(动态语言里面value和variable毫无关系,variable除了指向某个value以外别无用处。本质上variable就是某个数组元素或者某个哈希表项而已,本身不会包含value)。所以我在思考的时候,着重会注重一个概念“字面量”。在我认为,字面量、变量等等都是必须要**求值**的,他们的求值结果就是他们包含的值本身。这就是主表达式形式的外延含义。比如说"abc"你认为它仅仅包含一个匿名字符串字面量。是的,但是我认为如果它出现在表达式中,在求值过程中它本身被求值,没有副作用,求值类型是char*,求值结果是一个指向"abc"的指针,同时这个指针虽然是char*,但是语义限定其只读。我的意思是,我们不能说“变量只存值,在表达式求值中他们唯一做的事情是贡献出自己的值”,不是的,这里有更深的一个层次,应该是“变量包含值,在表达式求值中,变量名作为的主表达式本身也是一个表达式,它也会被求值,它求值的结果是就是这个变量名对应的变量所包含的值,它求值出的类型就是这个变量名对应变量的类型”。这么说才是完整的,而且这个前提和这个层次是无法被剃刀掉的,因为只有这样才能保存C的表达式系统概念上的完整性。

如果有动态语言基础,就可以很清晰地分清楚value,eval和variable。比如Python:
a = 1
a = a + 1
这句话是什么含义呢?第一句,a这个指针指向一个value,value的内容是int类型的1,第二句话的含义是,首先求值表达式a+1,然后让a指向这个求到的新值。注意这里值和a完全没关系,a仅仅具有一个“指向”和“重指向”的作用而已。虽然大多数动态语言会做优化,将int这种值保存在a所占的槽里,但是至少Python3不是这样,integer实实在在地是另外分配的不可变对象,而a仅仅是个指针而已。在这个前提下,a += 1和a = a + 1其实没有任何区别,并没有一个静态语言里面的“累加”含义。

关于字面量,其实也要被求值,但和变量的关系不大。仍以C++举例:字面量是和标识符一样的语法元素。字面量和一个无名实体——更确切地说是一个静态存储期的数组类型的对象(对于字符串字面量)或一个值(右值,对于其它字面量)对应。它的求值被反映到引用到这个无名实体上。

我想我明白了关于理解的根本差异。换种方式重新表达吧。
如果要略形式一点,理想情况下:
variable = (name, value)
name和value在形式上是对等的,必须存在,否则无所谓variable。
不过有个问题:什么样的variable是同一个variable?不同语言有不同的做法。

至少对于像C这样的存在词法作用域的静态语言来说,name一经引入就不可更改,而且是因为上下文受限的;value则不是。
对于这样的语言,更恰当的形式是:
variable = (name, value_entity)
这里value_entity和value被我刻意区分了。因为value在语言中其实是不同的概念,它们之间的等价性由它的类型和其它内容根据相关语义规则确定。value_entity则受限于适用于entity的不同的规则:同一性。例如对于C++来说,value_entity的原则应该是由ODR确定的这个variable是否引用了同一个对象——具有唯一定义,类型、存储和生存期都完全相同、不可分辨的对象——来分辨是不是同一个变量。而name是可变的,只是被声明限制具体应该是什么。(当然name也决定了一些重要的性质,如linkage。)value_entity的同一性决定variable的同一性,这样variable也就顺理成章具有作为entity的资格。
可以看出和literal的不同,也可以看出variable并不只是value,比如说C++这样就可以和存储直接关联。

而对于name可变或者使用动态作用域的语言来说,variable直接取代了entity的地位,恰当的形式可能是:
variable = (name_entity, value)
正好相反,不通过value来确定同一性,name体现entity的作用,在这里称为name_entity。variable的同一性由name_entity的同一性决定。于是不需要额外强调entity,value在这里的所谓被“包含”其实只是松散的关联。这也就是你理解的variable的真面目。但这类风格的定义如果不论具体的语言,看来只是遵从习惯,有被正式地明确过吗?

实际上,你之前引用的wiki的说法还是比较传统的,倾向于第一种。你使用的定义和里面的说法相悖,那里面可是明白地说了which contains some known or unknown quantity or information, a value。你之前对这个有异议过吗?
对于C适用的“变量”的概念,我的意见在这里与此相同。variable和value不可分割,所谓“变量”,总要有体现某种可变性的能力,这体现在它的value的可以变化上,而不是variable和value之间关联的变化。
变量名不是变量的组成部分,变量名依赖于变量而非相反。不考虑具体语言时,讨论变量同时可以不考虑变量名具体是什么,尽管变量名的总需要存在(否则无法使用这个变量)。需要考虑变量名时,变量名是变量外部关联的属性。
变量的值是变量的唯一必要组成部分。区分变量和变量值的原因是变量值和名称彻底无关,而变量总是和名称关联。

论坛徽章:
0
190 [报告]
发表于 2012-09-26 16:54 |只看该作者
回复 186# starwing83

好吧,小结一下:

共识:
0.老谭没学到家。
1.变量名可以作为表达式。
2.C没有正式的“变量”的概念,如果需要引入,它的定义尚没有共识。
3.假定变量的概念已被良好定义。不应该说变量就是求值。变量参与求值。
剩下的就是由变量的内涵引出的一些相关问题:
1.(对于C这样的语言来说)变量是不是需要包含变量名?
2.(对于C这样的语言来说)变量和求值之间的关系究竟应该是什么?

对于第2点,我的意见(这里明确的概念以C++为例):
变量参与求值,是因为变量的值是确定求值的结果的要素之一。但变量并不是求值这个过程作用的对象。求值作用的对象是表达式,并根据语法规则和语义规则(子表达式和完全表达式求值的关系)可以作用到变量名上。为了得到求值的结果,求值过程必须确定值,值包含类型,因此必须通过名称查找等方式明确名称所指的实体是什么,若发现名称未被声明、不能取得类型或和其它名称关联的规则违例时直接失败。这样,对于变量来说,求值过程中即体现变量名对变量的引用,连接了语法和语义,使语法能够作为判断行为的间接依据。

额外补充:
特别对于C++来说,实体的概念在技术上是必要的,它确立了ODR(One Definition Rule)能够被清晰表述。ODR这是唯一和语法规则、可诊断语义并列的正确性规则,指定实现必须拒绝哪些程序。ODR对于不同类别的实体有不同的细节表述。变量作为具名的对象(C++11还有引用),为区分对象是否和名称关联提供了遣词的途径,和ODR细节的表述直接相关。
ISO C++11
3.2 One definition rule [basic.def.odr]
1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.


实体、变量或者变量名对于C程序正确性和行为的描述不是必要的,但在此为了对语义的理解和讨论的简易需要明确得到共识。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP