碧海潮生's profile碧海潮生的小屋PhotosBlogLists Tools Help

Blog


    May 07

    设计笔记——程序的版式

    “GNU emacs能自动为你格式化C程序源代码……但是缺省情况下它的用处远远小于期望值──
    键入无数的monkeys到GNU emacs中绝不可能造出好的程序。”
    —— 《Linux kernel coding style》

    程序的版式好比书法,好的书法让人赏心悦目,清晰的版式让人一目了然。


    1 Tab与对齐

    “{”和“}”是代码块的分界符,一般应独占一行并处在同一列。
    代码块应使用Tab缩进编排对齐。如:

    while (condition)
    {
        statement1;

        if (condition)
        {
            statement2;
        }
        else
        {
            statement3;
        }
    }

    Tab size可设为8或者4。我个人倾向于将Tab size设为8。
    因为制表符本身就是8个字符的大小。

    《Linux kernel coding style》里这样叙述道:
    “有些叛逆主张试图把缩进变成4个(甚至是2个!)字符的长度,这就好象试图把PI定义成3是一样的。
    ……有些人说8个字符大小的缩进导致代码太偏右了,并且在一个80字符宽的终端屏幕上看着很不舒服。
    对这个问题的回答是:如果你有超过3个级别的缩进,你就有点犯糊涂了,应当修改你的程序。”

    当你打开一份程序,发现代码缩进没有对齐时,首先应尝试调整编辑器的Tab size设置。


    2 空行

    空行起着分隔程序段落的作用。空行不会浪费内存,所以不要舍不得用空行
    (虽然打印时会多消耗一些纸张,但那是值得的)。

    每个函数定义结束后要加空行。
    逻辑上紧密的语句之间不加空行,其他地方应加入空行分隔。


    3 空格

    代码行内的空格可以分隔关键字、标识符和运算符,用以突出被强调的部分。

    关键字之后要留空格。
    const、volatile、case等关键字后应留一个空格,否则无法解析关键字;
    switch、if、for、while等关键字后应留一个空格再跟左括号“(”,以突显关键字。

    函数名之后不留空格,紧跟左括号“(”,以与关键字区别。

    “(”向后紧跟;“)”、“,”、“;”向前紧跟。紧跟处不留空格。

    “,”和非行末的“;”后要留空格。如:
    function(parameter1, parameter2, parameter3)
    for (initialization; condition; update)

    赋值、比较、算术、逻辑、位运算符,如“=”、“+=”、“>=”、“<=”、
    “+”、“*”、“%”、“&&”、“||”、“<<”、“^”等双目运算符前后应加空格。

    单目运算符,如“!”、“~”、“++”、“--”等前后不加空格。

    像“[]”、“.”、“->”这类运算符前后不加空格。如:
    int *p = &x;不要写成int * p = & x;
    array[i] = x;不要写成array [ i ] = x;

    对于较长的表达式,为了紧凑起见可以适当地去掉一些空格。如:
    for (i = 0; i < MAX; i++)可写成for (i=0; i<MAX; i++)
    if ((a <= b) && (c <= d))可写成if ((a<=b) && (c<=d))


    4 代码块示例

    结构定义

    struct tag
    {
        member1;
        member2;
    };

    函数定义

    void function(arguments)
    {
        statement;
    }

    选择语句

    if (condition1)
    {
        statement1;
    }
    else if (condition2)
    {
        statement2;
    }
    else
    {
        statement3;
    }

    switch (expression)
    {
        case value1:
            statement1;
            break;

        case value2:
            statement2;
            break;

        default:statement3;
            break;
    }

    循环语句

    for (initialization; condition; update)
    {
        statement;
    }

    while (condition)
    {
        statement;
    }

    do {
        statement;
    } while (condition);


    5 修饰符的位置

    这是个有争议的话题。建议将修饰符*和&紧靠变量名,如:
    char *name;
    int *x, y;

    这样,y不会被误解为指针。


    6 注释

    C语言的注释符为“/*...*/”。

    注释通常用于:
    1> 版本、版权声明;
    2> 函数、宏接口说明;
    3> 重要的代码行或段落提示;

    不要试图在注释中解释代码是如何工作的,把代码是如何工作的视为一件显然的事情会更好。

    注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,但不要放在下方。


    7 结语

    编码风格是很个人化的东西,不应该把某些观点强加给任何人。
    但是,对于一个完整的项目或有继承性的课题来说,规范和传承编码风格是必须的。


    参考文献:

    [1] 高质量程序设计指南——C/C++语言,林锐
    [2] Linux kernel coding style,Linus Torvalds
    [3] GNU Coding Standards,Richard Stallman

    Comments (1)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    wrote:
    有时候非标准的代码书写方式可以带来意想不到效果,如下:
    void
    rb_define_method(klass, name, func, argc)
        VALUE klass;
        const char *name;
        VALUE (*func)();
        int argc;
    1. 可读性比较好;
    2. -_- Eclipse CDT这样的傻瓜插件辨认不出来 ... ....
    3. 该 snippet 截取自c-ruby 1.8.6
    May 7

    Trackbacks

    The trackback URL for this entry is:
    http://jx-kingwei.spaces.live.com/blog/cns!F7A152EB74B9576E!1489.trak
    Weblogs that reference this entry
    • None