1命名风格
(1)名字要准确表达用途
#define ONE 1
#define TEN 10
#define TWENTY 20
#define INPUT_MODE 1
#define INPUT_BUFSIZE 10
#define OUTOUT_BUFSIZE 20
(2)名字不是越长越好。全局变量可以用具有描述意义的长名字;
局部变量用短名字会显得程序更简洁
for (elementIndex = 0; elementIndex < numberOfElements;elementIndex++)
elementArray[elementIndex] = elementIndex;
for (i = 0; i < nitems; i++)
elem[i] = i;
(3)类的成员的名字,不要再啰嗦重复类名。
Class UserQueue{
int numOfItemsInQ, frontOfQueue, queueCapacity;
public int numOfUsersInQueue() {...}
}
Class UserQueue{
int nUsers, front, capacity;
public int getNumOfUsers() {...}
}
(4)用动词或者动词+名词定义函数名。
now = date.getTime()
putchar('\n')
(5)返回布尔值的函数名应该是一个命题,通常使用is作为函数名中的动词。
#define checkoctal(c) ((c) >= '0' && (c) <= '7')
if (checkoctal(x))...
#define isoctal(c) ((c) >= '0' && (c) <= '7')
if (isoctal(x))...
(6)名字尽可能简单明了,不要用“否定之否定”。
bool not_eof = true
if((ch = getchar()) == EOF)
not_eof = false;
bool is_eof = false;
if((ch = getchar()) == EOF)
is_eof = true;
2表达式和语句
(1)使用表达式的自然形式,即常见的易于理解的形式。
if(!(block_id < actblks) || !(block_id >= unblocks))...
if((block_id >= actblks) || (block_id < unblocks))...
(2)利用括号排除歧义。即使语法上不要求括号,也建议加上括号以便提高代码可读性
#define MASK 0x0F
#define BITS 0x01
if(x & MASK == BITS)...
#define MASK 0x0F
#define BITS 0x01
if((x & MASK) == BITS)...
(3)分解复杂的表达式。
*x += (*xp = (2 * k < (n - m) ? c[k + 1] : d[k--]));
if (2 * k < (n - m))
*xp = c[k + 1];
else
*xp = d[k--];
*x += *xp
3一致性和习惯用法
(1)使用一致的缩进和花括号风格(例如两行以上一定加花括号)
if(month == FEB){
if(year%4 == 0)
if(day > 29)
legal = FALSE;
else
if(day > 28)
legal = FALSE;
}
if(month == FEB){
if(year%4 == 0){
if(day > 29)
legal = FALSE;
}else{
if(day > 28)
legal = FALSE;
}
}
(2) 使用大多数人最习惯用法。(for循环设计的目的,就是让循环的起始状态,结束条件和步长一目了然)
i = 0;
while(i <= n-1)
array[i++] = 1.0;
for(i = 0; i < n; )
array[i++] = 1.0;
for(i = n; --i >= 0; )
array[i] = 1.0;
for(i = 0; i < n; i++)
array[i] = 1.0;
(3)用else-if 处理多路选择,一个判断应尽可能接近它所对应的动作
if(argc == 3)
if(fin = fopen(argv[1], "r")) != NULL)
if(fout = fopen(argv[2], "w")) != NULL){
while((c = getc(fin)) != EOF)
putc(c, fout);
fclose(fin);
fclose(fout);
}else
printf("Can’t open output file %s\n",argv[2]);
else
printf("Can’t open input file %s\n", argv[1]);
else
printf("Usage: cp inputfile oputputfile\n");
if(argc != 3)
printf("Usage: cp inputfile oputputfile\n");
else if(fin = fopen(argv[1], "r")) == NULL)
printf("Can’t open input file %s\n", argv[1]);
else if(fout = fopen(argv[2], "w")) != NULL){
printf("Can’t open output file %s\n", argv[2]);
fclose(fin);
}else{
while((c = getc(fin)) != EOF)
putc(c,fout);
fclose(fin);
fclose(fout);
}
3函数宏
(1)函数宏的缺点,直接替换,导致用到两次的参数会被替换两次,执行两次,可能直接导致错误。
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
while(isupper(c = getchar()))...
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
// 宏替换后的样子
while((c = getchar()) >= 'A' && (c = getchar()) <= 'Z')...
/*** ctype.h中定义的isupper更好***/
#define __isctype(c, type) \
((*__ctype_b_loc())[(int)(c)] & (unsigned short)type)
#define isupper(c) __isctype((c), _ISupper)
/*** 避免isupper的参数中写很多东西 ***/
while((c = getchar()) != EOF && isupper(c))...
(2)函数宏的缺点,直接替换,导致用到两次的参数会被替换两次,执行两次,也可能导致性能问题
#define ROUND_TO_INT(x) ((int)((x)+(((x)>0)?0.5:-0.5)))
size = ROUND_TO_INT(sqrt(x));
// 宏替换之后的样子
size = ((int)((sqrt(x)+(((sqrt(x)>0)?0.5:-0.5)))
int round_to_int(float x)
{
return (int)(x + ((x > 0) ? 0.5 : -0.5));
}
size = round_to_int(sqrt(x));
(3)如果一定要用函数宏,不要吝啬括号
#define square(x) (x) * (x)
y = 1 / square(x)
// 宏替换之后的样子
y = 1 / (x) * (x)
#define square(x) ((x) * (x))
y = 1 / square(x)
// 宏替换之后的样子
y = 1 / ((x) * (x))
4注释
(1)注释的目的是解惑,而不是增加疑惑。注释与代码要始终保持一致
if((country == SING) || (country == BRNI) ||
(country == POL) || (country == ITALY))
{
/* If the country is Singapore, Brunei or Poland
* then the current time is the answer time
* rather than the off hook time
* Reset answer time and set day of week
*/
...
}
(2)不要写没用的注释。
/* if "result" is 0 a match was found so return true
Otherwise, "result" is non-zero so return false */
return (!result)
return matchFound;
(3)用好的命名代替注释。
(4)用注释自动生成文档