OSC 第 112 期高手问答 -- 编写高质量的 C 程序代码

红薯 发布于 2016/03/14 10:03
阅读 6K+
收藏 27

OSCHINA 本期高手问答(3月14日-3月18日)我们请来了 @madengwei (马伟)为大家解答关于编写高质量的 C 程序代码的问题。

@madengwei  马伟,现任华康移动医疗技术总监,资深软件开发专家和架构师,微软最有价值专家(MVP)。拥有10余年软件研发和研发管理经验,擅长C、C++、.NET、Java等编程技术,专注于互联网应用的高性能架构设计与大数据挖掘,推崇互联网开源文化。

畅销IT技术书籍作家,著有《易学C#》和《ASP.NET 4权威指南》等畅销书,同时在大陆和中国台湾两地发行,广受读者好评。

为了鼓励踊跃提问,华章出版社会在问答结束后从提问者中抽取 5 名幸运会员赠予《编写高质量代码:改善C程序代码的125个建议》一书。

在通往“C语言技术殿堂”的路上,本书将为你编写出健壮、优雅、高质量的C代码指点迷津!内容全部由C编码的最佳实践组成,从C语言语法和C11标准2个方面深入探讨了编写高质量C代码的技巧与禁忌,一共总结出125条宝贵的建议。每一个建议对应C程序员可能会遇到的一类问题,不仅以建议的方式从正反两面给出了被实践证明为十分优秀的解决方案和非常糟糕的解决方案,还分析了问题产生的根源,犹如醍醐灌顶,让人豁然开朗。
本书针对每个问题所选择的应用场景都非常典型,给出的建议也都与实践紧密结合。书中的每一条建议都可能在你的下一行代码、下一个应用或下一个项目中崭露头角,建议你将此书搁置在手边,随时查阅,一定能使你的学习和开发工作事半功倍。

购买链接:http://item.jd.com/11857669.html

OSChina 高手问答一贯的风格,不欢迎任何与主题无关的讨论和喷子。

下面欢迎大家就编写高质量C代码方面问题向 @madengwei 提问,请直接回帖提问。 

加载中
1
天台道人
天台道人

@madengwei 

第一个问题:C语言接口设计时,如何返回变长字符串。
接口返回字符串时常有几种可能的实现:
A、外部开辟内存,类似sprintf。好处是可重复使用已开辟内存,节约时间空间,问题是把要开辟多大的问题交给了用户,也衍生了内存溢出隐患。
B、接口内部malloc后返回,比如char *myfunc(...);或者void myfunc(void **output_buf, size_t *output_size);好处是用着方便,缺点是频繁动态开辟内存已经可能衍生忘记free或者free不当的问题。
C、参考其他高级语言,自己设计一个动态字符串,比如redis中的sds实现,很多模块都会引用ta,缺点是增加模块间耦合。
D、在某些场合下直接返回一个大字符串中用户需要的子串的位置和长度,比如pcre在返回正则结果的时候。



第二个问题:怎样进行错误处理。
在如何返回错误的问题上,做法很多,有标准C下的errno,有Windows下的GetLastError,有返回负数定义的错误号,还有在返回值中径直用-1表示错误0表示正确的做法。几种方法都有看到使用(我习惯用最后一种)。


第三个问题:断言要如何使用。

有的国外大牛建议多用断言,且保持断言开启。但有的大牛实际上几乎不用断言,比如云风的skynet、linux内核等。这是为什么?什么时间用断言,什么时候不适合用断言呢?


第四个问题:字符编码对接口设计的影响。
Windows下很多接口都分ANSI和Unicode两个版本,linux下很少看到这么做的,您怎么看。


想请您说说对上述问题的看法。谢谢!

m
madengwei
其实你自己就已经阐述地很清楚了。对于变长字符串,B不建议使用,我也参考过redis里面的sds.c的设计,很不错的方案。对于错误处理,返回值中用-1表示错误0表示正确是大家最常用的也最简单直接的做法。对于断言,它的好处这里就不用多说了,个人建议使用。
1
让往事随风
让往事随风
有一些比较好的开源框架可以学习,比如:
  • Webbench
Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。
  • Tinyhttpd
Tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。
  • cJSON

cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。

cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。

  • Libev

libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。

  • Memcached

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库驱动网站的速度。Memcached 基于一个存储键/值对的 hashmap。Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。

  • SQLite

SQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。

  • redis
redis是高性能键值对存储系统,更多值得学习的C/C++知识:http://edu.51cto.com/course/course_id-3901.html
1
华章
华章
OSC 第 112 期高手问答 -- 编写高质量的 C 程序代码(获奖名单公布)
@金木道长 @Maserati_ @SVD @linux工人 @TymonHuang 
恭喜以上5位网友获得《编写高质量代码:改善C程序代码的125个建议》图书一本
请私信@华章 告知快递信息(姓名+电话+地址+邮政编码)
TymonHuang
TymonHuang
我忘了私信地址,请问还有么?
天台道人
天台道人
感谢华章,感谢osc
Maserati_
Maserati_
棒棒哒
SVD
SVD
感谢华章,感谢osc
0
宏哥
宏哥

C语言确实经典, 应该好好用

能抛开C++说C, 是正确的路。


0
Maserati_
Maserati_
@madengwei :之前做过一段时间的C++开发,在设计和划分模块的时候都是一个类一个.cpp和.h。现在做C语言开发时候在模块划分上思想还是扭转不过来,都是设计一个struct然后声明各个与这个 "类" 相关的函数,通过传递所谓的“this” 对 “对象”进行操作。模块文件还是一个.c,一个.h。我个人感觉现在的C代码写的不论不类,需要怎么样改变这种局面?
m
madengwei
楼上说的很对“语言是用来为编程思想服务的,而不是编程思想服务于语言,没必要倒置过来”。其实,不论是所谓的面向过程编程还是面向对象编程,都需要遵循一些最基本的编程思想与设计原则,要避免像你这样因为模仿C++调用习惯而导致的过度设计,这样也失去了C语言原本的简洁性。
macwe
macwe
C、C++只是工具而已,语言是用来为编程思想服务的,而不是编程思想服务于语言,没必要倒置过来。
0
SVD
SVD
@madengwei :每次编写C程序的时候,debug的过程真的是不如java IDE那么好用,在linux环境下调试起来也不是很方便,怎样才能真正的学会顺畅的调试C程序真的是一件不容小觑的事情,虽然在windows下有visul studio这样的工具,但是还是不爽,常常加载一些莫名其妙的header文件,报一些错,编译标准和历史很纷繁复杂,怎样形成一种编译环境和IDE统一的局面呢?
轻舞凋零
轻舞凋零
使用xcode 设置断点什么的杠杆的
强子大叔的码田
强子大叔的码田
linux下用gdb来debug程序很方便啊
m
madengwei
建议不要使用Visual Studio,多玩玩linux,习惯了就好。
SVD
SVD
回复 @macwe : 谢谢
macwe
macwe
Linux本身就是一个IDE,只不过入门比vs难、学习曲线比较陡而已。去学习它,适应它
0
虚无道长
虚无道长
@madengwei :目前公司的程序全局变量满天飞。个人感觉这样做有问题,请问这样做有什么优缺点?
花米
花米
我认为分业务统一管理全局变量是一个办法
quanwei9958
quanwei9958
全局变量就是全局程序状态,建议都用命名空间,单例结构体表示。
m
madengwei
全局变量的使用因业务设计而定,但过多的使用全局变量,很容易导致函数的不可重入性,从而也会降低程序的清晰性,我们往往难以清楚地判断出每个瞬时各个外部变量的值。当然,你也可以使用通过互斥信号量或者中断机制等方法来保证函数的线程安全。
macwe
macwe
全局变量,顾名思义是全局使用的变量。只要满足业务需求,使用得当,没什么优缺点之分。
0
烽火云烟
烽火云烟
@madengwei :就目前写c程序是推荐以传统的过程化方法编写还是使用面向对象的思想,如何用c语言很好的实现面向对象的特性,如多态,继承之类的。
m
madengwei
回复 @macwe : 这位兄弟说的很对“指针”。
macwe
macwe
指针
0
张盛山
张盛山
@madengwei : C语言学起来简单,用好真的很难。
m
madengwei
任何语言的学习都有一个过程,计算机存储与计算原理、语言特性、编程思想、设计原则与模式等都是任何一个编程者的必经之路。只不过C语言相当于其他语言来说,要求读者具有更扎实的计算机存储与计算原理等基础知识而已。
0
如比如比
如比如比
@madengwei :首先恭喜大作的出版,背后也有着艰辛。记得2000年左右林锐博士有本这样方面的出版,后来陆陆续续有些翻译国外的,您这次应该是结合新标准写的,除了这以外,您个人感觉还有什么独到之处吗?图片太不清晰了,看成sold了,实际是solid。
m
madengwei
剖析问题更加体系化与广泛化,不仅要让大家知其然,还要知其所以然。
返回顶部
顶部