zoukankan      html  css  js  c++  java
  • 读书笔记--C陷阱与缺陷(六)

    第六章

          1.预处理器:预处理器先对代码进行必要的转换处理,简化编程者的工作。

          它的重要原因有以下两点:

          a. 假如要将程序中出现的所有实例都加以修改,但希望只改动程序一处数值,重新编译实现。

          预处理器可以做到这点,通过将这个数值设为显式常量。

          b. C语言函数调用花销大,希望有一个程序块看上去像函数确没有函数调用的开销。

         

          2.宏定义的空格不能忽视

          宏定义只是简单的文本替换,记住这个本质可以避免很多错误。

          如: #define f  (x)  ((x)-1)

          上式意思是: f(x)代表((x)-1)    还是 f 代表(x)((x)-1)

          正确答案是后者。因为f与(x)之间多了空格;如果想表达前者的意思,应该定义为如下:

          #define f(x)  ((x)-1)

          括号也很重要,否则文本替换后运算会产生歧义。

     1 //#define f1  (x)  ((x)-1)
     2 #define f2(x)  ((x)-1)
     3 #define f3(x)  (x)-1
     4 int main()
     5 {
     6 
     7     int r1,r2,r3;
     8     //r1=f1(10)*2;
     9     r2=f2(10)*2;
    10     r3=f3(10)*2;
    11     printf("%d
     %d
    ", r2, r3);
    12 
    13     return 0;
    14 }

       其实f1的定义是无法通过的,在编译中报错x未定义。

          输出:r2=18, r3=8;

          因为 r3=(10)-1*2;

          所以宏定义的参数最好都用括号括起来!宏调用时的参数不要出现自增自减运算!

         

          3.宏不是类型定义

          其实之前章节就说明过使用 typedef 声明类型要由于使用 define;

          如: 

      

        #define T1 struct foo *
        typedef struct foo *T2;
        T1 a, b;
        T2 c, d;

      a,c,d都可以成功的定义为指向结构的指针,但是b却是定义为结构,非指针。

          因为 #define struct foo *a, b; b缺少了*

  • 相关阅读:
    UIFont的使用和字体类型总结
    LOJ-10100(割点个数)
    LOJ-10099(点双联通)
    poj-3177(并查集+双联通分量+Tarjan算法)
    图论:割点和桥
    牛客训练五:炫酷数学(思维)
    牛客训练五:炫酷路途(c++与dp)
    并查集的两种实现(按秩合并+路径压缩)
    牛客训练六:海啸(二维树状数组+vector函数的使用)
    牛客训练六:美食(贪心)
  • 原文地址:https://www.cnblogs.com/chenzhefan/p/7517933.html
Copyright © 2011-2022 走看看