#pragma预处理命令

来源:互联网 发布:思维脑图软件 编辑:程序博客网 时间:2024/05/01 19:38

C语言三种预处理功能

  1. 宏定义(#define)

    宏定义又称为宏代换、宏替换,简称“宏”。

    1. 不带参数
      格式:

      define 标识符 字符串

      其中标识符就是所谓的符号常量,也称为“宏名”。例:

      #define Pi 3.1415926//把程序中出现的Pi全部换成3.1415926

      说明:

      • 宏名一般用大写;
      • 使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义;
      • 预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查;
      • 宏定义末尾不加分号;
      • 宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头;
      • 可以用#undef命令终止宏定义的作用域;
      • 宏定义允许嵌套;
      • 字符串( ” ” )中永远不包含宏;
      • 宏定义不分配内存,变量定义分配内存;
      • 宏定义不存在类型问题,它的参数也是无类型的。
    2. 带参数

      格式:

      #define 宏名(参数表) 字符串

      例如:

      #define S(a,b) a*barea=S(3,2);//第一步被换为area=a*b; ,第二步被换为area=3*2;
      • 实参如果是表达式容易出问题,
      #define S(r) r*rarea=S(a+b);//第一步换为area=r*r;,第二步被换为area=a+b*a+b;

      最好给表达式中的参数都加上(),正确的宏定义是

      #define S(r) ((r)*(r))
      • 宏名和参数的括号间不能有空格;

      • 只作替换,不做计算,不做表达式求解;

      • 函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存

      • 宏的参数不存在类型,也没有类型转换。(类型转换由编译器在进行编译时负责)

      • 宏展开使源程序变长,函数调用不会

      • 宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。

    3. #undef

      作用:在后面取消以前定义的宏定义。一旦标识符被定义成一个宏名称,它将在作用域内保持已定义状态,直到程序结束或者使用#undef 指令取消定义。例:

      #define TEST_A 1#include "TEST.h"#undef TEST_A

      说明:在文件#include “TEST.h” 中宏定义#define TESTA 1起作用,过了这一语句宏定义就释放掉了,在test.h里,这个宏是有效的,然后出了这个头文件,又无效了。

  2. 文件包含(#include)

    其一般形式为:

    #include "filename"  

    尖括号表示预处理到系统规定的路径中去获得这个文件(即C 编译系统所提供的并存放在指定的子目录下的头文件)。找到文件后,用文件内容替换该语句。

    #include <filename>

    双引号表示预处理应在当前目录中查找文件名为filename 的文件,若没有找到,则按系统指定的路径信息,搜索其他目录。找到文件后,用文件内容替换该语句。

  3. 条件编译(#if、#else、#endif、#elif、#line、#pragma )

    一般形式有

    1. 如果表达式为真,就编译语句段1,否则编译语句段2

      #if表达式//语句段1#else//语句段2]#endif
    2. 如果表达式1真,则编译语句段1,否则判断表达式2;如果表达式2为真,则编译语句段2,否则编译语句段3

      #if表达式1//语句段1#elif表达式2//语句段2#else//语句段3#endif
    3. 如果在此之前已定义了这样的宏名,则编译语句段。

      #ifdef 宏名//语句段#endif
    4. 如果在此之前没有定义这样的宏名,则编译语句段。

      #ifndef宏名//语句段#endif

      else可以用于#ifdef和#ifndef中,但#elif不可以。

    5. pragma 预处理指令

      格式: #pragma Para pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 pragma once 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次 pragma warning pragma warning(disable:450734)//不显示4507和34号警告信息;#pragma warning(once:4385)//4385号警告信息仅报告一次;#pragma warning(error:164)//把164号警告信息作为一个错误。 等价于#pragma warning(disable:450734;once:4385;error:164)。#pragma warning(push)保存所有警告信息的现有的警告状态。#pragma warning(push,n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。#pragma warning(pop)恢复所有的警告信息 pragma push_macro 将指定的宏压入栈中,相当于暂时存储,以备以后使用 pragma pop_macro 将栈顶的宏出栈,弹出的宏将覆盖当前名称相同的宏 pragma deprecated warning C4995: “….” : 名称被标记为 #pragma deprecated这个错误意思是说,某个函数已经被标记为过时了,最好不要用,在将来的版本中,该函数可能就不存在了,可能会被更好的函数替代 …
    6. # line
      这个宏通常是和__LINE__宏一起使用的,__LINE__宏表示当前c语句在源文件中的行数,举个例子来说明 #line宏的使用:

        #include "iostream"  #line 100  using namespace std;  int main(int argc, char* argv[])  {    cout<<"LINE:"<<LINE<<endl;    return 0;  }  //输出结果是:__LINE__:104

      本来应该是输出:__LINE__:7,因为cout<<"__LINE__:"<<__LINE__<<endl;语句在第7行;但是有了#line 100,则从#line 100所在行的下一行被认为是第100行,所以输出的行号是104了。

0 0