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支持
Minus-C 一个最小化的C语言规范的更多相关文章
- 实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑
简介 以前写过一个补丁更新的文章,此处会做一个更精简的最小化实现,以便于集成.为了使逻辑具有通用性,将剥离对AFNetworking和ReativeCocoa的依赖.原来的文章,可以先看这里: htt ...
- 关于吴恩达机器学习支持向量机的问题,讲到对偶前有一个最小化f(w)使用拉格朗日求解时转化成一个最大的相等式的理解和一些困惑
(纯属个人理解) 参考: https://www.zhihu.com/question/267482928 https://www.cnblogs.com/90zeng/p/Lagrange_dual ...
- 一个最小化的SpringBoot项目
项目结构 项目基于Maven管理,注意使用了父pom <parent> <groupId>org.springframework.boot</groupId> &l ...
- 分享我自己的一个最小化安装CentOS6的初始化脚本
在自己的虚拟机上使用的基于CentOS6的系统初始化脚本 #!/bin/bash # #Filename:system_init.sh #Description:系统安装完成后,对系统进行一些配置,以 ...
- Effective Java 第三版——15. 使类和成员的可访问性最小化
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 手把手带你安装最小化suse 12 linux
当然. 你需要现有一个vmware,还要有一个suse的镜像,suse镜像可以直接去官网获取,只需要注册一个suse的账号就可以了,官网下载会有点慢,可以使用迅雷下载 F2 可以设置安装界面的语言,可 ...
- C# 隐藏最大化、最小化和关闭三个按钮
在Windows的窗体编程中,基本上每一个窗体都是一个最小化.最大化和关闭按钮的. 一.禁用最大化和最小化 对于最大化和最小化按钮,在C#窗体开发时,各一个属性来启用或禁用这两个按钮. this.Ma ...
- Monthly Expense(二分--最小化最大值)
Farmer John is an astounding accounting wizard and has realized he might run out of money to run the ...
- centos6最小化安装默认没有 NetworkManager服务
转载Centos6最小化安装中设置网卡默认启动 Centos 6.0版本提供了一个"最小化"(Minimal)安装的选项.这是一个非常好的改进,因为系统中再也不会存在那些不必要 ...
随机推荐
- php使用memcache与memcached扩展对key值的影响
php使用php_memcache时,key值为session_id()的值,也就是客户端cookie记录的值. php使用php_memcache时,key值为session_id()的值加上mem ...
- poj2387 Til the Cows Come Home
解题思路:最短路的模板题,注意一个细节处理即可. 见代码: #include<cstdio> #include<cstring> #include<algorithm&g ...
- Java调优之jvm和线程的内存分析
本文来源于铁木箱子的博客http://www.mzone.cc 这几天因为自己开发的一个网站在768M内存的机器上撑不起100多个用户的运行,因为每个用户启用功能后,系统将为每个用户分配8个左右的独立 ...
- Oracle RAC 服务器端连接负载均衡(Load Balance)
Oracle RAC服务器端的负载均衡是根据RAC中各节点的连接负荷数情况,将新的连接请求分配到负荷最小的节点上去.当数据库处于运行时,RAC中各节点的PMON进程每3秒会将各自节点的连接负荷数更新到 ...
- 几种Menu和几种对话框
一.Menu 1.OptionsMenu(弹出菜单) (1)显示弹出菜单布局必须要重写的方法 onCreateOptionsMenu 该方法必须返回true ...
- Android WebView中那些不得不解决的坑~~
前面那张hybrid开发心得 有人问 怎么解决不用onJsPrompt 来回调js函数的问题.其实很简单,就是在在你的jscalljava回调函数内 另外开个线程去load js代码即可: wb.po ...
- canvas小知识
清单 1. 绘制 canvas 矩形 function drawRect(){ var canvas = document.getElementById('canvas'); if (canvas.g ...
- PostgreSQL的备份和恢复
关于PostgreSQL的备份和恢复详细信息请参阅<PostgreSQL中文文档>. 备份: #pg_dump --username=postgres v70_demo > v70_ ...
- Java之--Java基础知识
一.软件基础知识 1.软件:一系列按特定顺序组织的计算机数据和指令的集合. 1)系统软件:DOS.windows.linux. 2)应用软件:QQ.扫雷等. 2.软件开发就是制作软件. 3.人与计算机 ...
- linux 为开机菜单加密码·
首先是在/boot/grub/menu.lst 里面添加密码的,但是需要是加密过后的,否则人家直接跑到你的menu.lst里面查看密码不就行了.... 于是,可以使用grub提供的md5加密功能: # ...