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!

时间: 2024-10-31 02:09:48

How to write perfect C code的相关文章

[读后感]从Code Review 谈如何做技术

还有9个电,争取把这篇发出去,里面有太同共鸣,只不过之前没能写出来, 一是文笔有限,总结不够明确,本文至少总结出了我想总结的6个观点,看来总结能力还是要提高: 二是不确认这是对的,所以不敢贸然写出来,看来奔四的程序员都有这些共同的想法,并非我一人,还有许多人... 着实说,代码审查,以前想过,但没做过: 代码审查确实很不错,不懂开发的测试人员其实从某种角度是用于粗暴地替代代码审查, 结果可知,花在修复 Bug 上的时间要比编码时间多 N 倍, 我想我们以敏捷方式来对付它,逐层皮儿地扒着做,做完一

从 Code Review 谈如何做技术

编者注:本文来自酷壳-CoolShell.cn 的陈皓 这两天,在微博上表达了一下Code Review的重要性.因为翻看了阿里内部的Review Board上的记录,从上面发现Code Review做得好的是一些比较偏技术的团队,而偏业务的技术团队基本上没有看到Code Review的记录.当然,这并不能说没有记录他们就没有做Code Review,于是,我就问了一下以前在业务团队做过的同事有没有Code Review,他告诉我不但没有Code Review,而且他认为Code Review没

打印机语言-ZPL指令设置QR code二维码无法转向的问题。

问题描述 ZPL指令设置QR code二维码无法转向的问题. 用ZPL指令生成QR CODE时,无法支持转向,该如何实现.如下^BQN,QR CODE只支持N一个参数. ^XA ^FO100,100 ^BQN,2,10 ^FD1234567890123456^FS ^XZ

Print2Flash出现&amp;quot;System Error. Code:1722. RPC服务器不可用.&amp;quot;错误解决办法

Print2Flash出现"System Error. Code:1722. RPC服务器不可用."错误. 一般来说这个应该是某个Windows服务没有打开所导致的问题.后来才发现:原来是Print Spooler这个服务没有启动,只要启动这个服务就可以了,启动的时候就不会报错了.

Win8系统安装过程中提示Error Code:0x0000005D错误的解决方法

  win8系统虽然在慢慢退出市场,不过还是有不少的用户喜欢Win8系统的风格,而在Win7升级win8系统的过程中会出现一些问题,有位用户遇到错误提示Error Code:0x0000005D的问题,该如何解决此问题呢?下面小编研究整理安装Win8系统提示Error Code:0x0000005D错误的解决方法. 错误信息如下: Your PC needs to restart. Please hold down the power button Error Code:0x0000005D P

code::blocks中把10^9定义成double型没有溢出定义成long double型却溢出

问题描述 code::blocks中把10^9定义成double型没有溢出定义成long double型却溢出 code::blocks(GNU GCC Complier)中把10^9定义成double型没有溢出,定义成long double型反倒溢出了.而10^9既没有超过double的范围,更没有超过Long double的范围,这是GNU GCC Complier的bug吗?我的code::blocks是16.01的,已经是最新版了. #include #include double a;

josn字符串-怎么获取type为2的后面的所有电力公司name和code

问题描述 怎么获取type为2的后面的所有电力公司name和code [{"code":"D1_3600","name":"电费缴纳","type":"2","categories":[{"code":"D1_3600_8401","name":"合肥供电公司"},{"code&

Custom tool error: Failed to generate code for the service reference &amp;#215;&amp;#215;&amp;#215;&amp;#215;&amp;#215;&amp;#215;. Please check other erro

开发工具:VS2010 问题描述: 在ProjectName.Web中创建的WebService服务,然后在项目中添加Add Service Reference,然后就报"Custom tool error: Failed togenerate code for the service reference ××××××. Please check other error andwarning messages for details. "这样的错误  新建.调用WebService 解

Packet Sniffer Code in C using Linux Sockets (BSD) – Part 2

In the previous part we made a simple sniffer which created a raw socket and started receiving on it. But it had few drawbacks : 1. Could sniff only incoming data. 2. Could sniff only TCP or UDP or ICMP or any one protocol packets at a time. 3. Provi