免费注册 查看新帖 |

Chinaunix

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

奶奶的靠语言机制保证安全 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2011-11-17 10:22 |显示全部楼层
回复 84# walleeee

>>个人感觉C++语言有些过度设计,很多事情,本来简简单单的就可以表达清楚,但是C++非要搞个模板,抽象什么的。
为什么说是感觉语言过度设计而不是用语言写的东西过度设计了呢?
>>对于C++11中被大家传唱已久的lambda,我个人实在看不懂好在哪里。。。是不是lambda真的像大家说的那么好?我感觉只是让代码更混乱而已。
理论上来说是没好到哪里去,同类物FP语言早就有原生支持并且更自然。实际上来说有些地方可以少写很多代码(函数对象的声明),如果习惯写泛型算法之类。
>>还有,auto这些东西本来就不适合C和C++这种级别的语言,不知道搞出来干什么,炫耀技术么?别告诉我这样可以让代码更好懂。
也是实际上可以少写代码,不用vector<xxx>::iterator i = v.begin();之类的了。

论坛徽章:
0
32 [报告]
发表于 2011-11-17 10:29 |显示全部楼层
要说过度设计,其实从C开始就一直存在。declartor和type name的语法就是典型的一个轮子两套制度。就算到现在C/C++也没有爬出这个泥潭,乃至Java都被影响。倒是C#拒绝int x[]只支持int[] x,不过反正本来也不要什么兼容了。再比如,int、signed、short、unsigned、long之类的冗余组合问题;没什么必要的东西却是核心语言特性的基本部分……

论坛徽章:
0
33 [报告]
发表于 2011-11-17 15:40 |显示全部楼层
回复 91# walleeee

>> C++正如其官方的说,提供了4中编程模式
官方?谁?
>>是对于绝大多数(99.999999...%)的人来说,多余的选择并非好事,也是负担,不知道你认同这一点不?
大道理说的是没错,不过这举的数字使你的话好像有一些Win用户数落*NIX的口气。
>>其次,语言过度设计和语言写的东西过度设计的本质来源在于语言自己提供了太多的选择,就像大杂烩,是一个组合级数的爆炸增长。
你是这样认为吗:比起不恰当的接口使人无所适从,提供正交的丰富的接口本身就是过度设计?
>>有很多的语言使用者有各种各样的恶习,把简单的事情复杂化,这一点我也不懂是为什么
这个我同意,同时我也很遗憾我搞不清也为什么会有这样的现象,也无法改变现状。
>>这一点看来你是支持C++了?
在这个特性上我中立。我自己是不会去用很花哨的东西,但是想到可能又会有一些低质量的代码因此增多,我不得不捏把汗。
>>我已经原理STL这种没什么大用,而又很复杂很低效的东西,因为他太不可控了,根本就无法根据需要进行调整。
就提供了能节约时间而言比C还是强一点。用的时候才发现不可控就太后知后觉了。至于复杂和低效,C也一样——你几乎无法用语言直接控制语言实现的状态来改变它行为,让它使代码看起来不复杂或高效。另外,有些东西是C学习了C++才不那么低效,像inline。“根本就无法根据需要进行调整”——是指调整什么?
>>至于你说的泛型,的确有用
是给C风格的静态类型系统擦屁股。因为弥补了一些核心语言特性的不灵活性,所以有用。
>>代码是在表达你的需要,同时也要让其便于让别人理解你想要什么。自己一时少些,偷懒,到头来害了别人,甚至有可能害了自己。
没错。但我举的例子用auto会影响可读性么?至于把语言特性用在不适用的地方乃至滥用,引用某人的话,“人的问题”。
>>这样一来,别人读你的代码就少了类型信息,如果很多变量都是这种缺乏类型信息的,那么读者会很头大
是么。至少在我举的例子上我不觉得。
>>另外这种方式实际可能会降低编译速度(当然你感觉不明显,但是如果是大工程你就知道了)。
请给出数据。理论上来说自动类型推导是会降低速度,但是照这么说复杂的嵌套类型的语法分析也会降低速度。哪个更多一些?
>>再次说明,以上是个人观点,可以讨论或者提点,但是请不要抨击,更别污蔑,说的有道理,本人会真诚感谢:)
赞同你讨论的态度。

论坛徽章:
0
34 [报告]
发表于 2011-11-17 16:12 |显示全部楼层
回复 92# walleeee

>> >>int x[], int[] x
>>这个只是个人喜好,我觉得并不是什么大问题,前面一种侧重说明x的元素都是int类型,而后面一种侧重说明x是一个int[]的类型。一个强调元素,一个强调变量本身。但是它们的功能在编译层面来说都是等价的,不知道你同意不?

表面上来看这样是没错。但是你归纳一下语法,再考虑一下当这种规则递归使用的复杂性的时候,可能就不会这么认为了。
举个例子:
http://bbs.chinaunix.net/thread-3619087-1-2.html
void (*tpsetunsol (void (_TMDLLENTRY *)(*disp) (char *data, long len, long flags))) (char *data, long len, long flags);
读起来爽么?写起来爽么?为什么这种东西能顺理成章地招摇过市?(编译器大概是没啥感觉……)
(严格来说还有那么点不公平:这里人一眼看过去很快搞清具体声明的是哪个标识符是不太靠谱的;机器可以和前面已经声明过的标识符比对,一有问题就罢【河蟹】工。)
再想想lisp之类如果改用中缀表达式那会如何?
编译层面是等价的,是的,对机器而言如此(标识符超长之类不考虑的话);但是,别忘了,这些代码的一部分价值来源于可以给人类阅读。既然如此,容易高效读写的东西好呢,还是顺应历史,认为很容易导致低效的方法更好?

>>这个是没办法的,要看当时的机器工艺,cpu对处理这些数据使用了不同的指令支持,另外,这些数据类型不同,在cpu级别上的效率也有很大的差异,一般来说,整数倍处理器字长的数据,处理越快。而C的设计是为了解决汇编对人的负担带大的问题,但是又不可能忽略掉机器性能和内存存储的要求,至少在那个年代是这个样子。当然,现在这一点大多数时候已经不那么非常重要。

于是时代的眼泪要与C共生共死么。

>>其实我觉得,asm/C/C++等是一代的,其后的Java/C#/...才是真正的高级语言。但是并不是说asm/C/C++不高级,只是用途不一致罢了:)

倒是有那么点感觉。不过C++离asm/C渐行渐远了。

论坛徽章:
0
35 [报告]
发表于 2011-11-17 16:58 |显示全部楼层
LZ对不起我继续歪下楼。这回是彻底歪了。
我对于程序设计语言的喜好并不主要由我已经实际用它解决了多少问题决定,而是直觉意义上的简单性,这包括:
1.写一个这种语言写的一般意义程序是否足够简单;
2.读上面写的程序是否足够简单。
无论如何,这里耗费大脑CPU时间最大的部分是表达的意义的解读和重现(至于记忆关键字和语法之类的,人适应起来比计算机快得多,而且也是一次性投资,不用花精力重复学习,相比可以忽略)。
通常人不自觉地分析和实现语义会用到以下几类方法:操作语义、指称语义和公理语义。实际上这是有严格定义的方法,不过我这里泛化地指和这些方法接近的方法分类。
举个例子:认为学C需要先学汇编的,是在说操作语义王道;一般的C教材是以指称语义为主,操作语义为辅;C标准则混合三种方式解释语义,且公理语义>指称语义>操作语义。
这些方法都有合理的成分,但单独任何一种方法都有其局限性。例如操作语义抽象困难,指称语义容易过度抽象,公理语义在描述和解决问题上手续繁杂。我认为具体使用哪类方法,应该看需要而定。如果定义一种新语言,那么采用公理语义方法奠基会比较简单(像Lisp)。可惜C语言不是,它混合了前两者,最缺乏第三种方法,并间接导致各个实现之间的差异过于明显。后来标准化的时候不得不添加许多细节,我想这是主要原因。
我认为我的大脑最适应于指称语义方法,它对于解决来自于普遍的问题域的问题最具有操作性。引用喂鸡:
指称语义的一个重要原则是“语义应当是复合性的”: 程序段的指称应当建立自它的子段的指称。最简单的例子是: “3 + 4”的意义确定自“3”、“4”和“+”的意义。
于是学习和解决新的规则的复杂度是线性的。操作语义方法效率可能近似或略高,但它的前期准备需要占用远远超过线性的空间复杂度;而公理语义方法在解决问题时效率都远远劣于指称语义,尽管它的解的质量可能更高。
所以不得不死记各种语法细节的才能算会用,会用之后仍然得靠冗余关键字来“帮助”我写出正确代码的语言我并不认为对我有多少价值,即使这类语法本身只是很少的一部分。
C在这个方面上做的还好。没有BASIC的啰嗦也没有PASCAL的死板,却也不算很不严谨而无从归纳,对规则的指称进行抽象还是可行的。算是取得了一个平衡。
可惜由于时代的局限性,在静态类型系统上做过了头。被写死在语言规则的类型语义不可能无视,迫使我付出防止习惯于语言的规则影响思维的代价。在必要时突破这种障碍的唯一设施就是借助于类型转换的void*,如果不算宏的话。
而C++在这点更精确更容易。所以我认为C++至少更适合我。表面上的复杂已经被习惯地过滤掉了,C++对我而言并不比C难多少(标准文本倒是啰嗦了不少,但更清楚)。
我不认为C++在一般意义上更优秀。但它至少能让我的思维更简单轻松,如此而已。(对于学一门语言就要用这门语言思维的人来说就算了,鸡同鸭讲。)

论坛徽章:
0
36 [报告]
发表于 2011-11-17 17:03 |显示全部楼层
回复 96# zylthinking

歪楼能力自觉不够,还是免了。
到贴吧继续锻炼去了……

论坛徽章:
0
37 [报告]
发表于 2011-11-18 01:46 |显示全部楼层
回复 98# walleeee

>>呵呵,好几本都里面都有说这个,具体我也记不清那么多,不过我给你找了几篇wiki看看

这个观点我知道,在一些著名的C++教材中见过。不过我得说,即使说“C++能支持这些范型”,但是具体应该在哪些场合下用哪种,似乎并没有公认的答案。

>>这个我不太明白你的意思,你是想表达我认为“正交的丰富接口就是过度设计”这一观点么?我不是这个意思,正交而丰富的接口本来就是接口设计的原则之一,任何程序库的设计者都应该深刻理解正交和丰富的概念。

你之前说过“语言过度设计和语言写的东西过度设计的本质来源在于语言自己提供了太多的选择,就像大杂烩,是一个组合级数的爆炸增长”。我想了解你为什么会这样说。在某些细节上,或许的确有不必要的“太多的选择”,但我认为整个语言以及标准库的设计大体上还是符合“正交而丰富的接口”的精神的,并非哪个看起来有用于是就添加了哪个,而是需要尽可能考虑它们之间的协同作用会导致的改变后才添加新的内容。(请注意,我这里说的接口设计并不是指库;语言本身的规则——尤其是这门语言特有的特性,也应当被约定为接口。)

>>而你看现在的一些软件工程方法,是否有一些本末倒置了...
某些熊孩子玩过头了……形式主义,的确本末倒置。

>>语言的本质应该是让你轻松而充分的表达你的思想,而非其他,尤其是带来争执。

作为语言存在的最根本的目的,的确如此。
当然,考虑文化因素又另当别论了。

>>C其实宏也蛮好用的,只是我不知道为什么这么多人抨击,就像goto,我个人觉得都蛮好的,看场合了。

C的宏确实还好用,但是宏和其它特性的实现形式上的距离太大,并且因此造成了一些问题。在文本层次上直接处理代码可能会造成直接能阅读到的和经过替换后的代码的极大差异。对部分地解析源文件的解析器(例如用于语法高亮)的编写,宏也带来额外的困难,不利于优化。

>>调整是指STL内部的各种扩展算法,比如内存分配器等。
你是指根据现有的分配器难以改写?那么就应该重写一个。内存分配器本来就是设计成被整个替换掉的东西。而实际的内存分配的逻辑也当然不用全写死在分配器内部。

>>其实所有语言(所有的计算机编程语言)在计算能力上都是图铃等价的,没有谁比谁更强大,他们的区别只是谁比谁更方便。C++在做泛型和数据抽象的时候相较于C的确是高级语言。

在计算能力上的等价不是抽象能力上的等价。只考虑对计算的表达能力,那么高级语言只要有一种就应该能满足所有需要了;事实并非如此,因为决定语言盛衰的核心用户不是计算机而是人。不同程序设计语言的代码有不同的特点,有的较易读但写起来麻烦,有的则相反。此外,它们往往对应用领域有不同的侧重。如果一种语言能够高效地使人用于解决问题,在它的用户眼里就显得比较强大,反之亦然。也就是说,“方便”是“强大”的重要组成部分,至少对于人来说是这样。
考虑通用领域的程序设计,是否能找到一种公认的在计算和抽象能力都足够强大,并能用于解决任何与计算机相关领域问题的工具呢?这是一个我感兴趣的问题——长远来看,它至少可以为自动程序设计等终极手段提供一个过渡。我的观点是,C++是这个星球历史上最接近这个目标的语言,尽管对达成这个目的仍然远远不及。C++在面向的问题领域是最大的,而C似乎从来就没有这个野心。C的完全静态类型系统不能适于解决一般领域问题的需要:这里出现了矛盾。C++引入动态类型的概念,并在此基础上提供了虚函数、RTTI等运行时类型相关的抽象。然而C++在这步上没有走多远,最大原因或许正是为了和C维持源码级兼容。现实是,在更加上层,无法获得静态类型系统优势的场合,C++是失败的,大多数用户选择更轻便的语言。或者说,迄今为止没有任何真正“通用”的语言有接近这个目标的希望。我为此感到遗憾(也许只是时机未到~谁知道呢)。

>>例子代码也应该按照这个要求要强制,不然又有很多同学会照着清华某“砖家”书里的“例子代码”来写而丢了工作:)
强制或许不必要,但是给出什么场合下不适合用这个特性的建议是应该的。

>>这个我是说“可能”,只是直观的感觉,因为这一点我目前没有具体的数据,而且也没时间去研究G++。但是我说这个话是很有把握的,不信你也可以自己测测。(ps.找个大型的工程,比如qt,然后把里面所有函数内的变量都改成auto,这一点用sed比较好做到,然后再来编译一下)

我的直观的感觉是如果一对一的话,auto在大部分情况下确实应该更慢,毕竟auto依赖于对整个声明的解析,而嵌套类型名只需要依赖于id-expression。
尽管我这里也是纸上谈兵,不过测一下应该符合你的预期。
不过有一点,同样是直观的感觉,auto多消耗掉的时间相对于不同翻译单元之间重复实例化模版的时间来说应该小得多。

论坛徽章:
0
38 [报告]
发表于 2011-11-18 02:00 |显示全部楼层
回复 99# walleeee


>>当然,这是个人品味问题,不多深究。

也许是不必深究。我只是有时候会突然忍不住中缀表达式洋溢着的bad-smell。

>>计算机工业的发展,兼容是非常重要的一个原则,如果不是迫不得已,没办法兼容了,后续产品都是必须兼容前代的。所以,必须共生共死。

关于兼容的重要我很清楚。不过为什么没有勇气增加过渡而使以前不合理、不再符合现实需要的东西逐渐消失呢?
其实这里的例子是有的。比如,C99不再支持implicit declaration。不过,做不到很彻底。而且,C比起C++来说,或许是因为实现较简单的原因,既有实现的影响更大,对标准的依赖性更小,也相对鲜少有人对新的东西表现出热情。
关于这里的原因,可能是成本、习惯之类的原因,这是可以理解的。然而这个氛围总是让我觉得不是味道。Sigh.

>>而且,C语言不见得只是给传统的体系结构编写程序,还用在各种各样的体系结构上,你可以让C把所有的整数都当成一个类型来处理,但是其他人呢?做密码的可能需要能处理字节,做普通软件的可能希望能处理字符。C是为了适应各种需求而精心设计的类型系统,当然也可能会给一部分人带来很小的不便,这个是没办法。

C语言的对于各种体系结构的机器而言,它的普遍适用性经过了历史检验,毋庸置疑。基于语言能力的角度上,我没认为“C把所有的整数都当成一个类型来处理”会是好事,我希望见到一个受到更少历史遗留物束缚的,在同样的领域中易用的工具。

>>另外,要明白,现在跑在各种机器上的总代妈量中有70%都是很老的代码,甚至几十年前的代码,他们不活了?

老的代码需要维护,但不表示新的代码永远无法取而代之。
有些地方不作出改变,历史的包袱越来越重,说不定以后就再也没有改变的机会了。

论坛徽章:
0
39 [报告]
发表于 2011-11-18 02:09 |显示全部楼层
回复 100# walleeee

iostream确实很不怎么样。就算不管实际上不顶用,光从纯粹面向对象角度来说都能算是典型的过度设计,最明显的地方是滥用继承。
当然iostream用到的一些东西是有比起cstdio来说是有一些积极性的,比如格式化输出的接口是的静态实现方式。要输出一个int,printf就免不了的解析"%d"这样的字符串,而流操作符至少在理论上可以不用。这样在不需要动态配置格式的时候就能有更高的效率。可叹的是iostream没好好利用这个优势,性能上一塌糊涂,还没甩掉效率比C实现更低的locale的包袱……不但性能低了,格式的动态可配置性也丢了,写起来还不会简单到哪去,编译又慢目标代码还体积膨胀……实在无语。
我个人也更习惯于scanf/printf的格式。不过或许是口味问题,有些人觉得流操作符的格式更清楚。
boost的字符串处理我没用过。不过因为上面说过的理由,我认为基于iostream或其类似物的东西真没什么大前途。

论坛徽章:
0
40 [报告]
发表于 2011-11-18 20:05 |显示全部楼层
回复 106# zyzbill

STL有虚函数?
iostream和locale倒是有一堆。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP