1、命名规则
标识符的命名要清晰直观,有明确的含义
fine:
int error_number; int number_of_completed_connection
awful:
int n; int nerr; int n_comp_conns;
标识符的长度应当符合“最短长度”和“最多信息”的原则
程序中不要出现仅靠大小写区分的相似的标识符
int x, X; void foo(int x); void FOO(float x);
程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会让人误解
用正确的反义词组命名具有互斥意义的变量或相反动作的函数等
int minValue; int maxValue; int SetValue(...); int GetValue(...);
尽量避免名字中出现数字编号,处分逻辑上的确需要编号
awful:
#define EXAMPLE_)_TEST_ #define EXAMPLE_!_TEST_
fine:
#define EXAMPLE_UNIT_TEST_ #define EXAMPLE_ASSERT_TEST_
变量和参数用小写字母开头的单词组合而成,常量全用大写的字母,用下划线分割单词
BOOL flag; int drawMode; const int MAX = 100; const int MAX_LENGTH = 100;
如果不得一需要全局变量,则是全局变量加前缀g_(表示 global)
int g_howManyPeople; int g_howManyMoney;
变量的名字应当使用“名词”或者“形容词 + 名词”
float value; float oldValue; float newValue;
函数命名应以函数要执行的动作命名,一般采用“动词”或者“动词 + 名词”的结构
// 找到当前进程的当前目录 DWORD GetCurrentDiretory(DWORD BufferLength, LPTSTR Buffer);
对于数值或者字符串等常量的定义,建议采用全大写字母,且单词之间加下划线“_”的方式命名
#define PI_ROUNDES 3.14
2、if 语句
整型变量与 0 进行比较操作是,应当将整型变量用”==“或”!=”直接与 0 比较
fine:
if (value == 0); if (value != 0);
awful:
if (value); if (!value);
不可将浮点变量用“==”或“!=”与任何数字比较,应该设法转化成“>=”或“<=”形式
awful:
if (x == 0.0);
fine:
if ((x >= - EPSINON) && (x <= EPSINON)); // EPSINON 是允许的误差(即精度)
判断一个指针变量是否为空时,应当将指针变量用”==“或”!=“与 NULL 比较
if (p == NULL); if (p != NULL);
3、循环语句
- 在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的放在最外层,以减少 CPU 跨且循环层的次数
- 如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体外面
4、宏和常量
使用宏定义表达式时,要使用完备的括号
awful:
#define RECTANGLE_AREA(a, b) a * b #define RECTANGLE_AREA(a, b) (a * b) #define RECTANGLE_AREA(a, b) (a) * (b)
fine:
#define RECTANGLE_AREA(a, b) ((a) * (b))
better:
#define FOO(x) do { \ printf("arg is %s\n", x); \ do_something_useful(x); \ } while(0)
使用宏时,不允许参数发生变化
5、参数的规则
参数的书写要完整,如果函数没有参数,则用 void 填充
void SetValue(int width, int height); // fine void SetValue(int, int); // awful float GetValue(void); // fine float GetValue(); // awful
参数命名要恰当,顺序要合理
awful:
void StringCopy(char *str1, char *str2);
fine:
void StringCopy(char *strDestination, const char *strSource);
6、函数内部实现的规则
return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时被自动销魂
char *Func(void) { char str[] = "hello world"; ... return str; }
7、断言的使用
内存复制函数:(如果 assert 的参数为假,那么程序就会终止,并出现提示对话,说明在某个地方引发了 assert)
void *memcpy(void *pvTo, const void *pvFrom, size_t size) { assert((pvTo != NULL) && (pvFrom != NULL)); // 使用 assert byte *pbTo = (byte*)pvTo; // 防止改变 pvTo 的地址 byte *pbFrom = (byte*)pvFrom; // 防止改变 pvFrom 的地址 while (size-- > 0) { *pvTo++ = *pbFrom++; return pvTo; } }
8、内存管理
- 用 malloc 申请内存之后,应该立即检查指针值是否为 NULL,防止使用指针值为 NULL 的内存
- 不要忘记为数组和动态内存赋初值,防止将未被初始化的内存作为右值使用
- 避免数组或指针的下标越界,特别要当心发生“多1”或者:少1“操作
- 动态内存的申请与释放必须配对,防止内存泄露
- 用 free 释放了内存之后,立即将指针设置为 NULL,防止产生”野指针“