zoukankan      html  css  js  c++  java
  • Minus-C 一个最小化的C语言规范

    资深C++程序员都不会对C++编程规范太陌生,C++实在太复杂,以至于所有项目都需要裁剪一个子集共项目组内使用。经过在家休息这一小段时间,我发现其实C语言更需要一个相同的规范,这就是本文的目标,最大可能规避C语言的黑暗面。

    这里说的“不支持、不使用”,是指在没有明确要求的程序中,不主动使用。但在特殊场景下(如调用外部接口等),有些黑暗的角落我们还是要去了解。

    大体上分成这几个部分,这些有些还是只是一个初步的想法,逐步会进一步扩充和裁剪。

    1.语言标准和编译器

    如果我说出建议使用C99和GCC是不是有很多人长叹一口气,不过C99事实只用到了很少一点特性,大部分编译器都支持,比如说//注释。选择GCC是因为它广范的可获得性和一致性,而主要以GCC做为一个验证标准来看待。

    2.文件格式

    这部分只要求两点,一是包含基准头文件,stdc99.h。C语言的头文件实在不标准。二是使用前注释,而不是行注释和后注释。

    3.数据类型选择

    只选用char, unsigned char, int 这几个基本类型,64位系统程序中应该还要增加一个long long 。

    不使用typedef的结构体和指针,即结构体都有前缀struct 。

    不使用共用体。

    不使用enum类型,但使用enum来定义常量。

    数组类型,需要要特别说明,不强制使用。

    只在有明确要求的地方使用double类型,小心不精确的表示。

    4.函数使用

    一般不使用malloc,以静态分配为主,必须进行动态内存管理时,必须使用这四个一组的函数完成。

    xxxalloc/xxxsize/xxxfree/xxxextend

    不使用scanf/printf这种内嵌的语言。

    不使用(...)式的可变参数,除非可变参数是同一类型。

    5.表达式

    接受使用+,-,*,/

    除提领‘*’外,不接受++与其它运算符同时出现。

    不使用&,|,^,~,<<,>>,见后面“位操作”

    不使用?:

    不使用","逗号表达式,但接受在声明和函数参数中使用。

    6.位操作

    由于位操作在有符号问题上操作复杂,推荐使用以下函数形式的宏,完成位操作。u/s分别表示unsigned和signed

    ushfleft,ushfright,uset,uclear,uisset,umask

    sshfleft,sshfright,sset,sclear,sisset,smask

    7.语句

    不使用do ... while/switch...case,推荐使用if else/while。

    对于数组循环处理,推荐使用for (int i = 0; i < n; ++i) 这个标准结构,必要的索引通过第二个变量计算出来。

    8.数组

    使用数组+长度两个变量来表示一个数组。

    除首地址外,建议其它元素地址使用&a[i]结构来取得。

    数组循环处理使用标准结构,例如,奇数索引的元素赋值为1:

    for (int i = 0; i < n; ++i) {

      a[2*i + 1] = 1;

    }

    9.抽象数据

    进程有唯一性的抽象(全局状态),定义为模块。

    通过void foo_init(void)或void foo_init(int argc, char** args)这样的函数初始化。

    通过void foo_close()这样的函数关闭,通常这些调用会在main函数中完成。

    一般在头文件中声明为:

    struct foo;

    struct foo* foo_new();

    void foo_dosomething(struct foo* o, void* error);

    在C文中定义访问struct foo和访问内部成员的函数

    #include "namespace/foo.h"

    struct foo {

      成员

    };

    10.动态抽象数据

    头文件中增加声明

    struct foo_ops {

      void (*op1)(void);

          void (*op2)(void);

    };

    struct foo* foo_new(struct foo_ops* ops, void* data);

    对应的C文中,在struct foo中要增加定义

    struct foo {

      struct foo_ops *ops;

      void* data;

      其它成员

    };

    11.错误处理机制

    主机制可以通过setjmp/longjmp这样的全局状态完成,这应由main函数完成。

    程序库内部应提供非侵入式的错误处理机制,例如返回错误状态,惯例如下:

    int parse_options(int argc, char** args, struct error* err);

    错误状态保存在err中,如果不关心错误,可以通过传入0来忽略,但函数本身应把状态记录在全局的错误对象上。 在前一个错误未清除的情况,函数应没有动作,也不修改全局错误对象。输入了错误指针时,把全局对象复制给错误指针。

    12.其它杂项和风格问题

    不应忽略{},总是使用{}来表明范围。

    使用//注释,C99支持

    使用按需声明变量,C99支持

     

  • 相关阅读:
    c++的const总结
    http框架--Forest 的使用
    SQL 语句大全
    Mysql 总结
    【Spring注解驱动开发】使用@Scope注解设置组件的作用域
    注册中心EUREKA(二)--配置列表
    Linux命令发送Http GET/POST请求
    真正理解NIO
    高并发下接口幂等性解决方案
    代码量统计工具
  • 原文地址:https://www.cnblogs.com/ahuangliang/p/programming_style_of_c.html
Copyright © 2011-2022 走看看