C语言进阶_笔记 第二章 预处理

来源:互联网 发布:程序员在什么系统算 编辑:程序博客网 时间:2024/06/04 19:59

1.文件的包涵方式,明白其区别及不同编译环境下的不同。

    #include "文件名"

    #include <文件名>

2.宏定义。


    由于宏在使用时只是简单的替换,所以定义宏时一定要注意被替代部分的“整体性”,如:

     #define   A   12+12
     #define   B   10+10

    与  

    #define   A    (12+12)

     #define   B    (10+10)

     明显后者要安全的多的多的多,例如做运算A*B,用第一种宏肯定是要出问题的。

3.带参宏定义。


在上面的宏中使用“typeof(y) _y = (y)”这样的转换是为了防止x和y为一个表达式的情况,如x=i++,如果不转换,那么i++就会多执行几次操作,得到的就不是想要的结果。如果使用了“typeof(y) _y = (y)”这样的转换,就不会出现这样的问题了。我们可以通过下面一段代面的宏中使用“typeof(y) _y = (y)”这样的转换是为了防止x和y为一个表达式的情况,如x=i++,如果不转换,那么i++就会多执行几次操作,得到的就不是想要的结果。如果使用了“typeof(y) _y = (y)”这样的转换,就不会出现这样的问题了。

注:typeof()是C99标准中添加的。VC++6.0是不支持的,linux系统下的gcc可以很好的支持。

4.变参宏定义。

    #define print(...) printf(__VA_ARGS__)

   在这个宏中,“...”指可变参数。可变参数的实现方式就是使用“...”所代表的内容替代__VA_ARGS__.在linux下用gcc编译如下代码:

   #include<stdio.h>

   #define print(...) printf(__VA_ARGS__)

   int main()

   {

  print("hello world------%d\n",1111);

return 0;

   }

  运行结果为:hello world------1111

  预处理中还常常使用“#”和“##”,大大提升了宏的便利性。

  #1.## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元。
  #2.#符是把传递过来的参数当成字符串进行替代。

5.宏定义常见错误。

   #1.不要在字符串中使用宏,如果宏名出现在字符串中,那么将把宏按照字符串来处理。

  定义STR为Hello World,则:printf("字符串中的宏:STR和不在字符串中的宏: %s\n",STR);

  的执行结果为:字符串中的宏:STR和不在字符串中的宏: Hello World!

   #2.宏中定义指针时一定要注意。如

   #define INT_P int *

   INT_P p,p1;

   我们进行一下宏扩展,将“INT_P p,p1;”扩展为“int* p,p1;”,这是问题就出现了。

6.#pragma指令的使用。

   (1).#pragma message("消息")。

   (2).#pragma once
   如果在头文件的开头部分加入这条指令,那么就能保证头文件只被编译一次。

   (3).#pragma hdrstop
   该指令表示编译头文件到此为止,后面的无需再编译了。

   (4).#pragma pack()

   其作用是取消之前设置的字节对齐方式。


0 0