How to write perfect C code
Several days ago, I was involved in an argument about choice of C or C++. What I ignored was "language is less important than coder". a bad C# writer only write shit-like C# but a professional C programmer could design perfect C, Notwithstanding C# is much more powerful than C,
So how to write perfect C code? We just illustrate that by cJson, a famous pure-C tiny json formatter.
1. Power C pointer, make point operation awesome
The string-comparison of cjson like melody, this ability might need you a lot experience:
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;
if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)
if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
So how you write a same strcasecmp function? Try more C code.
2. Reasonable code indent
Someone might tell you write code with same indent-style, "the wrap position, where to put a bracket..." However, most people are accustomed to reading left to right without pause. So a better code reader understand is more important than that so-call rule and style just like follows:
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }
ep=value;return 0; /* failure. */
}
Does Code below make it more easy to understand than standard indent style? As you can easily compare difference between each case of switch structure.
3. Chain-style function design
Chain-style function means you can invoke them with merge them into a chain, as A(B(C)).
Linq (a chain-style code sugar ) greatly improve beauty of C#, could
make your code designed like: Select.Where.Orderby... As standard C do
not offer extend-function. But you could still make the chain like
Order(Select(Where(Data))) . Some little bit harder ,but much more
easier than other code style, just like code in cJson:
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. *
The difficulty is the rope which connect modules into a chain. In
Linq, it's a interface called IEnumerable, a compiler-level state
machine. In cJson code behind, it's the position of processing pointer.
4. Hook me!
Standard C do not have delegate, function override. But there are some other powerful mechanism called hook, achieved by function pointer. You could change a function pointer behaviour by assign a different function with same parameters and return value. Example as follow:
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
Awesome right? You can change memory allocation and free behaviour by using hook!
5. Offer default value of function parameters
In order to make your user more convenient when using your perfect library, please offer them some override functions! C might not allow you define two same name function by different parameter table. But you could still do this:
/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
6. Marco and #define
Marco is only way to make C transplant in different platform.
6. Improve algorithm!
C style code is different than C# or Java, the languages with powerful libraries. Sometimes because of compatibility or performance, using STL or some 3rd libraries is not a good choice. So you need to achieved them by yourself. This does not means you should write "Stack.c" or "Stack.h" to define a full-functional stack. It's too heavy and unnecessary,right? But the core algorithm of stack will greatly affect your code style by merge an easy array-achieved stack by several simple code.
The example in cJson is tree structure, as json is a
nature tree. The author merge tree algorithm into the code by recursive
and pointer without any trace. Perfect!
Try more C code, try more perfect improvement, guy!
作者:热情的沙漠
出处:http://www.cnblogs.com/buptzym/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?