正确地黑C
转载:http://tieba.baidu.com/p/3190068223?pn=1
本版暂时当作提纲,不做详细展开讨论,以后可能更新。
注意:本文主旨不是政治正确。
1.设计
C的设计相对于同期来说是局促的。C语言具有明显的历史局限性是不争的事实。
类型系统是一个显著的例子。理论上,typed lambda calculus在当时(70年代)即便没有流行也已经有了数十年的发展,但是C的设计并没有有效利用当时的理论成果,还在前人的经验上开洞(比如奇葩的函数指针转换)。
类似地,数组类型也不是第一类实体,也会有类型上的修正。
这些无聊的设计除了让抽象变复杂,限制用户的自由外,唯一的好处也许就是顺应之前的具有局限性的语言实现的习惯了。不过,今非昔比,这样的设计并没有简化现在的语言实现——不管是C还是其它语言。
这种仓促的设计影响深远。C++至今仍然把一些肇始于C的奇葩转换保留在“标准转换”中,以至于重载的规则加倍复杂——考虑到兼容问题以及维护规则本身的困难,这些无谓的复杂性今后可能永远也无法移除。
左值(lvalue)是一个不幸的设计。一开始作为文法性质,并没有考虑到潜在的复杂,以至于后来引入const后,功能和区分左值在相当大范围内重复了(若完全一致反倒还好点)。这点另外有说过,按下不表。而这里重要的是,也无法指望丢弃冗余性(C++甚至变本加厉)。
当然,考虑历史的主干,C来自于B,来自于BCPL,来自于CPL,来自于ALGOL 60,来自于ALGOL 58,来自于FORTRAN。这些语言都没有这方面的合理经验积累。所以C的设计的局限,并不难想象。
也有一些其它的不足之处——丢弃有用的特性导致的倒退。不过,有些被纠正过来了,例如BCPL后扔掉的单行注释(//),被某些C方言、C++和C99以及其它一些C-like派生重新吸收。
还有一些奇葩的莫名其妙的地方。B里面叫vector的东西说的好好的,怎么到C里面就变成array了呢?只是因为加了个残疾的“数组类型”?(B是没好意思说成有类型的……)为什么array而不是vector就非得能对元素“O(1)访问”——这种偏见是谁发明的?(另一个不良后果是A.Stepanov搞STL的时候没词了就顺手捡了个……)
2.标准化的有效性
不能否认,在被规范化的语言(而不是实现)针对平台的可移植性来讲,C差不多应该是现在的语言中最强的了。ISO C++在某些少数极端情况下的可移植性的确不如ISO C(见WG21/N4049)。而其它语言,假定1字节不等于8比特的大小就足够打退堂鼓,若不够可以再加上允许原码/反码作为有符号数表示——这两者是ISO C和ISO C++都明确支持而其它大部分语言规范都与之矛盾的东西。
标准化的一个重要作用是取得共识,避免一些重复工作,提升可移植性,减轻用户(包括实现者)的负担。若标准被架空而没有被实际使用,标准本身就失去了绝大部分意义。
这里的一个反面素材是C#,.NET的实现都出到5.0了,ECMA-334到现在还是当年2的版本……(还有C#里把finalizer叫成destructor的奇葩导致混乱的说法在ECMA里被纠正了,MSDN上仍然将错就错。)
啥,ECMA是区域性组织,不够权威?——人家现在叫ECMA International好不好。不过不够权威好像是能坐实点,C++/CLI在ISO标准化被英国的意见驳回,ECMA就通过成ECMA-372了……
那么这里就拿C++比较好了。同样是ISO/IEC JTC1/SC22下的工作组,两者的产出看似类似,效果大相径庭。
而敢无视WG21的实现——据我所知,一个都没有。即便GNU早年隐晦地表达过和标准划清界限,现在来看在C++前端是口嫌体正直了。反观GNU C,这个效应就弱得多。
简而言之,ISO C虽然整体上是有效的,但是对于语言实现者来说,效力略为不足。
概括起来,这有两方面原因。
其一是WG14本身的活动没有WG21强调“open”。WG21的文档早就被公开多年,而WG14的没记错的话到2012年才被公开。
可能是由于C++本身的复杂性以及历史教训(轻率引入export和dynamic exception specification)需要避免消极的design by committee的影响,参与C++工作讨论的非委员会用户活动非常显著,Google Groups里讨论标准提议的论坛已经开设了好几年。isocpp.org也是一例。WG21甚至在github上拥有公开仓库允许用户pull request修改标准草案的内容。
反观C方面呢?一个对应的东西都没有。
作为工作产出来看,WG14公开的paper也要比WG21少得多(得多……)
C++比起C真有复杂到这种程度么?还是说C的“社区”(暂且这么说)在传统上就“不够进取”?或者根本不愿意达成共识呢?
第二点恐怕未必。POSIX就比较活跃了。
可笑的是,维护POSIX的Austin Group和WG14之间也能出现琐碎的意见分歧。参见WG14/N1174。
原因是其二——还是C的设计。
C欠缺了太多东西。
上面的隐晦分歧就是指,是不是在标准化的接口中,允许函数返回动态分配的对象然后让用户自行释放?ISO C的意见是“不”——于是asprintf乃至strdup都不可能出现在ISO C标准库,但这个原则之前看来从来没有被正式提起过。而POSIX方面以及其它传统C用户大概不会这么认为(特别是GNU)。
其它主流语言里还有这种奇葩问题么?
而ISO C新引入的东西,很多也不是自身的设计。
ISO C11引入的sequenced before的wording,是WG21/N2239提出来的。注意,是C++的paper,C后来照搬过去了。
(嘛,C++比较激进删除了之前ISO C引进的sequence point,不过这里有个bug,漏了sequenced after这个定义,我邮件过去了,处理情况见github.com/cplusplus/draft/issues/61。)
C11同时照搬过去的还有多线程和atomic的基本概念。由于语言特性上的先天不足,C没法做到C++的优雅(虽然这词普遍恶心,但用在这里的确不错)。(看看那个奇葩的_Atomic……)
C11还不得不引入了某种意义上的“临时对象”,这种手段又是埋坑。
C11绝无仅有的东西呢?哦,比如generic-selection?我问一下,这里谁对_Generic有印象的?知道它是怎么回事的?能说清解决了什么问题,并且是怎么起作用的?有多少人在实际代码中用过?在其它语言中类似的东西是什么?
ISO C比ISO C++多出来的,特别是近来新添加的,差不多尽是广大C用户都难以认同的琐碎玩意儿……
WG14,请不要玩脱。
3.用户素质
本来我在这里不想攻击任何人。但是C的用户在辩护语言和实现表达自己的观点时,表现出来的槽点明显比其它语言的用户多得多,并且不少自以为得计,优越感爆棚。忍无可忍。
在这里起到负面影响的用户都可以概括成不同程度的“不懂装懂”“在不熟悉的领域里瞎BB”“误导”,不过可以分成那么几类(也有不少复合的):
a)原教旨主义
认为C是程序设计语言发展历史上的“正统”——却连老祖宗ALGOL的地位和影响都不知道,甚至和亲爹B语言之间的差别都一问三不知。
b)盲信
不管可以引证的依据和理性思辨而盲目认同一些经不起推敲的观点(比如C比起其它高级语言总是“性能高”“开发效率低”)。
c)无知
缺少其它语言的使用经验却臆测行为和实现。甚至对C自身的基本概念(比如“对象”“左值”“未定义行为”)都说不清楚。
d)不独立思考
缺乏怀疑精神,对符合固有印象的说法来者不拒,却不考虑理由。“我听说”……“人家×××就是用C写的!”
e)缺少专业基础
没有PLT常识,对其它语言品头论足,对其中和C设计不同之处——而不是不足之处做出非理性的批评。
从经验上来看,这些用户中最核心的部分同时是UNIX的脑残粉——包括一些只用过Linux然后把自己包装成UNIX粉的。
这些用户,绝大多数都说不清楚C(也许还有UNIX)历史和发展方向之类的详细问题,要提一些现有实现的缺陷和可改进之处都支支吾吾,甚至说不清楚为什么好用,满足了什么需求(某些果粉都比他们更强一点)。
脑残粉本身不足一提,不过当一些“知名人物”也具有这些特质之后,他们就好像找到了什么被撑腰的了——却不知道很多“大师”在评论这里的问题上很多也是半外行,跟普通用户无异。
4.专治各种不服:有谁自认为对C本身了解更深刻而全面反对以上观点的(特别是挂名在WG14内的——有么?),欢迎对号入座战个痛。
EOF
正确地黑C的更多相关文章
- [工作积累] Google/Amazon平台的各种坑
所谓坑, 就是文档中没有标明的特别需要处理的细节, 工作中会被无故的卡住各种令人恼火的问题. 包括系统级的bug和没有文档化的限制. 继Android的各种坑后, 现在做Amazon平台, 遇到的坑很 ...
- Swift5 语言指南(二十一) 嵌套类型
通常创建枚举以支持特定类或结构的功能.类似地,定义纯粹在更复杂类型的上下文中使用的实用程序类和结构可能是方便的.为此,Swift允许您定义嵌套类型,从而在它们支持的类型定义中嵌套支持枚举,类和结构. ...
- tcpdf中增加微软雅黑的正确方式
找了很多增加字体的方式,不过提供的命令行下增加字体的命令是错误的,下面这个命令是验证过可以用的,不管是win还是linux活着mac都可以. tcpdf对中文的支持就不太好, 当然也可以支持, 比如里 ...
- Win + Manjaro 双系统、双硬盘安装方法 正确引导系统方法 黑屏解决方法(不瞎写,百分百有用)
1. 前言 本教程只涉及 Win + Manjaro 双系统.双硬盘安装过程中的核心要点,不涉及具体步骤,不注意这些要点,安装之后是进不去 Manjaro 系统的. 详细的安装步骤网上已经有很多了,这 ...
- iOS正确解决隐藏导航栏后push和pop或dismiss和present闪黑问题
情景: 一级页面不显示导航栏 ,二级页面显示导航栏. 方法一 适用于push/pop: 一级页面中 - (void)viewWillAppear:(BOOL)animated { [super vie ...
- PYTHON黑帽编程1.5 使用WIRESHARK练习网络协议分析
Python黑帽编程1.5 使用Wireshark练习网络协议分析 1.5.0.1 本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks At ...
- Python黑帽编程 3.1 ARP欺骗
Python灰帽编程 3.1 ARP欺骗 ARP欺骗是一种在局域网中常用的攻击手段,目的是让局域网中指定的(或全部)的目标机器的数据包都通过攻击者主机进行转发,是实现中间人攻击的常用手段,从而实现数据 ...
- Python黑帽编程 3.3 MAC洪水攻击
Python灰帽编程 3.3 MAC洪水 传统的交换机(我只对我目前使用的交互机做过测试,按照常识只能这样表述)在数据转发过程中依靠对CAM表的查询来确定正确的转发接口,一旦在查询过程中无法找到相关目 ...
- 从“黑掉Github”学Web安全开发
Egor Homakov(Twitter: @homakov 个人网站: EgorHomakov.com)是一个Web安全的布道士,他这两天把github给黑了,并给github报了5个安全方面的bu ...
随机推荐
- shell中的IFS详解
在bash中IFS是内部的域分隔符,manual中对其的叙述如下:IFS The Internal Field Separator that is used for word splitting af ...
- WPF与输入法冲突研究之二:汉字输入法会导致WPF程序的崩溃!
如果是输入非汉字的数据信息,可以添加一下内容: xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCo ...
- shell脚本一条命令直接发送http请求(xjl456852原创)
我们知道nc命令是一个网络工具.可以连接tcp/udp.也能模拟发送http请求. 现在介绍通过shell脚本,一条命令直接发送http请求. 命令如下,可以对下面的地址等信息自行修改: #!/bin ...
- NetAnalyzer笔记 之 三. 用C++做一个抓包程序
[创建时间:2015-08-27 22:15:17] NetAnalyzer下载地址 经过前两篇的瞎扯,你是不是已经厌倦了呢,那么这篇让我们来点有意思的吧,什么,用C#.不,这篇我们先来C++的 Wi ...
- Android应用盈利广告平台的嵌入方法详解
一.如何学习Android android开发(这里不提platform和底层驱动)你需要对Java有个良好的基础,一般我们用Eclipse作为开发工具.对于过多的具体知识详细介绍我这里不展开,我只 ...
- 【转】Xcode升到6.4插件失效,与添加插件不小心点击Skip Bundle解决办法
转载自:http://www.jianshu.com/p/d51547d29309 今天升级了xcode到6.4 发现之前装的插件不能使用了.这里有一个解决的方案: 步骤如下: 一.查看Xcode的U ...
- DEV LookUpEdit 使用方法
public class field { public string Name { get; set; } public string Explain { get; set; } } List< ...
- 关于css3的rgba
在rgba之前,我们应该知道rgb.它就是红色R+绿色G+蓝色B.那rgba是什么?简单的说就是在rgb的基础之上加上一个通道alpha.他的语法如下: r 红色值.正整数(0~255) | 百 ...
- PixelFormat 枚举
成员名称 说明 Alpha 像素数据包含没有进行过自左乘的 alpha 值. Canonical 默认像素格式,每像素 32 位. 此格式指定 24 位颜色深度和一个 8 位 alpha 通道. Do ...
- sqlserver插入datetime
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")