阳光烂灿的日子

--记录所有碎碎念

C陷阱与缺陷(2)

| Comments

第二章:语法陷阱

2.1理解函数声明

int f,g; 声明f,g的类型为整型.

int ((f)); 当对((f))求值时,((f))的类型为整型,由此可推知f也是整型。

int *pf; 这个声明中,*pf是一个整型数,所以pf是一个指向整型数的指针。

int *g(),(*h)();

对于*g(),因为()的优先级高于*,*g()就是*(g());令pf=g(),则*g()就是*pf,整个表达式变成 int *pf; 因此可知pf 是一个指向整型数的指针。由此可知对g()的求值结果是一个指向整型数的指针,也就是说g()的返回值是指向整型数的指针。最后得出,g是一个函数,该函数的返回值类型为指向整型数的指针。

对于(*h)(),令pf=(*h),则 pf() , 很明显看出,pf是一个返回值为int的函数。即*h是一个返回值为int的函数,因此h就是这个函数的指针,即h为返回值为int的函数的指针。

int (*h)(); 表示h是一个指向返回值为整型的函数的指针,因此:

(int (*)()) 表示一个“指向返回值为整型的函数的指针”的类型转换符。

假定fp是一个函数,调用fp所指向的函数为: (*fp)();ANSI标准允许程序员将上式简写成fp()。但要记住这只是一种简写形式。

*fp()实际上与*(fp())的含义完全一致,ANSI C把它作为 *((*fp)())的简写形式。

(void (*)()) 0; 将常数0转型为“指向void的函数的指针”类型。

对于 fp(),可变成:(*(void(*)()) 0)();

//有点玄而上学了!

2.2运算符的优先级问题

这个问题在第一章的时候提了一下!现在举个自己的例子!

r=hi>>4+low ;

我曾经天真地认为hi会先右移四位然后才和low相加。但错误狠狠地教训了我!这个表达式的顺序是hi右移了4+low个位。”+“的运算符的优先级大于“>>”的优先级!

具体的就不说了!记住下面两点:

1.任何一个逻辑运算符的优先级低于任何一个关系运行符。

2.移位运算符的优先级比算术运行符要低,但是比关系运算符要高。

另加自己的一条:如果不确定运算符的优先级,那就给你想先执行的语句加上括号!方便阅读并且保险!

2.3注意作为语句结束标志的分号

(1) if(x[i]>big);

(2) big=x[i];

注意,第二句和第一句的if没有关系!因为第一句的if之后有了一个分号,表示if语句判断之后执行了一个空语句。然后到了第二句!

再来看看少了分号的情况!

if(n>3)

return

logrec.date = x[0] ;

logrec.time = x[1];

程序原意是n大于3时就返回!但在return后面少了一个分号,程序就变成了n大于3时返回logrec.date的值了!

struct logrec{

int date;

int time;

int code;

}

main()

{

}

在这里,结构体后面少了个分号,程序变成了main函数的返回值是上面据说的结构体!这些都是不得不注意的问题!

2.4 switch语句

switch后面的case会顺序执行,因为C语言把case标号当成真正意义上的标号,程序的控制流程会径直通过case标号,而不受到任何影响!因此需要在每个case后面加上break来退出执行流!

2.5 函数调用

C语言要求在函数调用的时候即使函数不带参数,也应该包括参数列表,因此,如果f是一个函数:

f(); 是一个函数调用语句,而

f; 是一个什么也不做的语句,这个语句计算函数f的地址,却没有调用这个函数!

2.6 “悬挂”else引发的问题

没啥好说的,注意if和else的对应问题就可以了!写代码的时候注意好缩进能比较好地防止这个问题!或者是即使没有else语句对应的if语句也写上去,只为了对应,写上去的else执行空语句就可以了!

Comments