C Traps&Pitfalls总结

C陷阱与缺陷,偶然在图书馆看到,也不厚,不到200页,于是就接过来,两天看完了。
书中提到的大部分特性我之前多少都有些了解,这里总结了一些。应该说还是有收获的,现在总结下从这本书中学
到的新东西。
  • 语义方面
1)P31页练习2-1:
C语言中允许数组的初始化列表中出现多余的逗号,例如:
int a[]=
	{
		1,2,
		3,4,
	};
为什么这种特性是有用的?
answer:当初始化列表很大的时候,方便自动化的程序设计工具(代码编辑器)自动处理。

2)嵌套注释
C语言不允许嵌套注释,但有些编译器还是会实现这个功能。书上提到的一个简单测试方法是int a=/*/*/0*/**/1;
然后看a等于多少:对于支持嵌套注释的编译器,会连续读入两个"/*",而且刚好有两个"*/"与之对应,所以a=1;而
对于大多数C编译器,第二个"/*"属于注释里的内容,继续分析可知a=0*1。
但是对于IDE来说用不了这么麻烦,注释的时候是有代码高亮显示的,直接可以看出来。由于此书是在ANSI-C刚刚成
型时候写的,可能那时候并没有这么多集成开发环境,向当时的程序员一个个小心翼翼的Tricks而致敬!

3)宏
自从投靠了C++,我就更没有什么机会用到宏了,"const int"成为了替代品。可能宏对我最直接的好处是上学期抄
毛概练习册的时候,发现“解放思想,实事求是”,“毛泽东思想邓小平理论...重要思想”重复的次数太多,于是索性
在页首洋洋洒洒写下:

#define JS 解放思想,实事求是
#define MD 毛泽东思想
使用宏最应该注意的一点就是多加括号,慎加空格和分号。更难发现的一类错误是带参数的宏的副作用,最常用的宏:
#define max(a,b) ((a)>(b)?(a):(b))
当程序中出现max(a,b++)的时候就会出现问题,因为经过预处理之后,b++在程序里面出现了两次。
标准库中的putc(),getchar()等函数是用宏实现的,使用时小心副作用。
宏中有if语句时也要小心,比如有
#define assert(a) if(!a) assert_error(__FILE__,__LINE__)
那么当assert出现在if...else语句中的时候就会出现意外的错误。
还有一种可能的错误是
#define char* chpnt
然后定义两个char指针:chpnt p1,p2;//这样只有p1是char *类型,而p2是char类型
总之,当宏跟程序的其他部分扯上关系后错误就很难发现了。额,反正我也不怎么用得到宏,权当了解。
  • 可移植性
这个最烦了。
4)标识符
就是变量名,首字母不能是数字,最大长度不能超过6,也就是bigeast和bigeasr对于编译器来说是不可区分的。
还好我查了一下这是早期的ANSI标准,现在长度似乎没有一个标准,估计几百应该没问题。

5)取模运算
歧义主要在负数取模的结果上,既然不通用,对负数还是不要取模了吧。
  • 编程技巧
6)边界计算与不对称边界
相信很多人都曾为多1或者少1的错误纠结过,比如一个长度为n的数组,遍历的时候我们一般用:
for(int i=0;i
而不用
for(int i=0;i<=n-1;++i)
就是使用了“不对称边界”,从而达到了一个比较直观的效果。
在二分查找中掌握了这个技巧可以少犯错误。二分老是犯晕,直接copy书上的范例:
用不对称边界的二分查找:
int *bsreach(int *t,int n,int x)
{
	int lo=0,hi=n;
	while(lo<hi)
	{
		int mid=(hi+lo)>>1;
		if(x<t[mid])
			hi=mid;
		else if(x>t[mid])
			lo=mid+1;
		else
			return t+mid;
	}
	return NULL;
}
采用对称边界:
int *bsreach(int *t,int n,int x)
{
	int lo=0,hi=n-1;
	while(lo<=hi)
	{
		int mid=(hi+lo)>>1;
		if(x<t[mid])
			hi=mid-1;
		else if(x>t[mid])
			lo=mid+1;
		else
			return t+mid;
	}
	return NULL;
}
还有对printf()函数的一些介绍,我发现这函数功能还真是多,于是再写一篇一块总结吧。
Advertisements
上一篇文章
下一篇文章
留下评论

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: