一。词法陷阱 ----词法分析器
1.符号之间空白讲被忽略。 (tab,space, enter)
2.贪心法:编译器必须对2个连在一起的符号做出判断:将其作为分别的符号对待,还是合起来对待。
规则:每一个符号应该包含尽可能多的字符。直到字符串已不再可能组成一个有意义的符号。
3. 046八进制 46十进制 0x46十六进制
二。语法陷阱
1. () 高于* : float *g(); 函数 , float(*g)();指针。
2.破解申明:
1.求值逐步分解:float(((f))); --> 求(((f)))得f .
2. float (*h) ();表示一个函数指针, ( float(*) () )0; == > (* (void (*)())0 )();
** 将其转型为该变量的类型,只需要把变量名去掉即可;float(*h)() --> float(*)(); float *f; ---> float* ;
example:void (*a)(int); --> void( * signed(xxx) )(int); ----> void (* signal(int , void(*)(int) ) )(int)
三。运算符
()【】。 》 * ~ & ! 》 + - * / 》 > <
三。语义陷阱
1.浅拷贝,深拷贝
2.&两边都计算, &&一边比成功了另一边就不进行计算。
四。连接
* 编译器把代码绎成连接器能看得懂的内存,二进制结构。
*编译器吧具有static修饰的变量,函数都重新命名后给连接器,所以static的东东都不具备重名。保证其仅仅在单个文件中的有效,而在整个文件中独一无二。
*连接器的一个重要工作就是处理这类命名冲突。:要么禁止、警告等。。。。标记定义与未定义。。
*连接器的输入是一组目标模块和库文件。输出是一个载入模块。
*头文件的出现很好的分离了申明与定义,解决了重命名的问题。凡是引用头文件的源文件都将使用同一个变量、函数。
五。库函数
errno的正确使用:
if( fopen() )
{
检查errno.
}
而非
fopen()
if(errno)[;;;;]
六。预处理:
#define f (x) (x)-1 ---> f代表(x) (x)-1 所以预处理要注意空格这东西。
*如何计算int double char 的最大小值:int 2^31 -1 (32位--> 4*8) double:2^63-1(64-->8*8) char 2^7-1(8--->1*8)
int4字节,double8字节,char1字节,字节 * 8==总位数。