码迷,mamicode.com
首页 > 其他好文 > 详细

C陷阱与缺陷 之 各种知识技巧

时间:2015-01-27 00:28:55      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:

1.词法分析中的“贪心法”   编译器将程序分解成符号的方法是,从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分:如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。(需要注意的是除了字符串与字符常量,符号的中间不能嵌有空白)

   eg:

y = x/*p     //p指向除数,而实际上/*会被编译器理解为一段注释的开始,编译器讲会不断的读入字符直到*/出现为止

改为下列 

y = x / *p    //或者更加清楚一点写作 y = x / (*p)

eg:

a+++++b   //请理解其含义是什么?

上式唯一有意义的解析方式是:

 a++   +   ++b

可是我们也注意到根据贪心发规则上式应该被分解为 

((a ++ ) ++ ) + b    //这样是错误的,因为a++的结果不能作为左值

因此编译器不会接受a++作为后面的++运算符的操作数。

对于为何a++为何不能做为左值是因为

首先对于i++的实现是:  

              

  int   temp;  
  temp   =   i;  
  i   =   i+1;  
  return   temp;  

而++i 的实现是:

i = i + 1;
return i;

所以对于我们提出来的问题已经能得到解决了:

i++=5; 是错误的是因为i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通
过地址对temp进行操作.(换句话说就是不能作为左值),因为temp是一个临时变量

 

 

 

 

2. 函数语法声明  函数指针的理解

float   *g(),   (*h)();
//g是一个函数,该函数的返回值类型为指向浮点数的指针。
//而h是一个函数指针,h所指向的函数的返回值为浮点类型。
//于是我们可以得到如下;
(float  (*)  ()  )
//表示一个 “指向返回值为浮点类型的函数的指针” 的类型转换符

当然我们可以使用typedef来解决这种复杂的函数指针的类型转换符

typedef float (*HANDLER) ();
float (*(HANDLER)  fxx ) ();

例如:

当计算机启动的时候硬件讲调用首地址为0位置的子例程。我们必须设计一个c语句以显示调用该子例程,可得如下语句:

(* ( void  ( * ) () )  0) () ;

分析如下: 如果fp为一个指向返回值为void类型的函数的指针,那么(*fp)()的值为void,fp的声明如下:

void  (*fp) () ;

但是,我们一旦知道如何声明一个变量,也就自然知道如何对一个常数进行类型转换,将其转型为该变量的类型: 只需要在变量声明中的变量名去掉即可。

//因此,将常数0转型为“指向返回值为void的函数的指针”类型,可以如下写:
( void (*) () ) 0
//因此,我们可以用 ( void (*) () ) 0 来替代fp , 从而得到:
( * (void  (*) () ) 0 )  () ;
//末尾的分好; 使得表达式成为一个语句

//使用typedef 能够使表述更加清晰
typedef void (* funcptr) () ;
( * (funcptr) 0) ();

 

 

3.某比较

  a与b的相对大小顺序是否和c与d的相对大小顺序一样,可以这样写:

 

a<b  == c<d

 

C陷阱与缺陷 之 各种知识技巧

标签:

原文地址:http://www.cnblogs.com/wizzhangquan/p/4251685.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!