zoukankan      html  css  js  c++  java
  • 【C语言】pragma

    #pragma comment (lib, "libgsl.a")

    这是告诉编译器在编译形成的.obj文件和.exe文件中加一条信息,使得 链接器在链接库的时候要去找libgsl.a这个库,不要先去找别的库。

    加入这条语句后,就不需要把libgsl.a这个文件额外通过链接器加入到工程里了。

    #pragma comment( comment-type ,["commentstring"] )
    comment-type是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker之一。
    commentstring是一个提供为comment-type提供附加信息的字符串。
     
     

    #pragma 的使用

    尽管 C 和 C++ 都已经有标准,但是几乎每个编译器 (广义,包含连接器等) 扩展一些 C/C++ 关键字。

    合理地应用这些关键字,有时候能使我们的工作非常方便。下面随便说说 Visual C++ 中 #pragma

    指示符的使用。

    一、用#pragma导出DLL函数

        传统的到出 DLL 函数的方法是使用模块定义文件 (.def),Visual C++ 提供了更简洁方便的方法,

    那就是“__declspec()”关键字后面跟“dllexport”,告诉连接去要导出这个函数,例如:


    __declspec(dllexport) int __stdcall MyExportFunction(int iTest);

        把“__declspec(dllexport)”放在函数声明的最前面,连接生成的 DLL 就会导出函数

    “_MyExportFunction@4”。

        上面的导出函数的名称也许不是我的希望的,我们希望导出的是原版的“MyExportFunction”。

    还好,VC 提供了一个预处理指示符“#pragma”来指定连接选项 (不仅仅是这一个功能,还有很多指示功能) ,

    如下:


    #pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")

        这下就天如人愿了:)。如果你想指定导出的顺序,或者只将函数导出为序号,没有 Entryname,

    这个预处理指示符 (确切地说是连接器) 都能够实现,看看 MSDN 的语法说明:


    /EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

       @ordinal 指定顺序;NONAME 指定只将函数导出为序号;DATA 关键字指定导出项为数据项。

    二、指示文件只包含一次

        在头文件中,一般在整个工程中我们只要包含一次就够了,但是如果我在多个 .c/.cpp 文件中都要包

    含着个头文件,比如 Windows.h,那很多声明等等岂不是有两次了?解决这个问题的传统的方法是在头文件

    开始出用

    #define 定义一个宏,比如 Windows.h 中:


        
          #ifndef _WINDOWS_#define _WINDOWS_
        
        
        P>    然后在文件结为加上 #endif,这样就可以避免被包含多次。但是这样的后果是代码的可读性较差

    (个人观点),VC 给我们提供了另外一个途径,那就是在文件的前面加上:#pragma once    是不是很方便?

    三、使警告无效    有时候我们不得不对变量进行强制转换,由此引来编译器的一番警告,特别是 C++ 中

    ,类型检查相对于 C 更为严格。这虽然不影响什么,但是看起来多不爽——我是故意要这样的,

    你警告什么!:)这时候你看到警告类型,

    比如“warning C4311: “类型转换” : 从“HHOOK”到“BOOL”的指针截断”,在前面加上:

    #pragma warning(disable: 4311)    编译器就没话说了:)。

    四、指定连接要使用的库    比如我们连接的时候用到了 WSock32.lib,你当然可以

    不辞辛苦地把它加入到你的工程中。但是我觉得更方便的方法是使用 #pragma 指示符,指定要连接的库:

    #pragma comment(lib, "WSock32.lib")五、显示编译消息    没多少用处,举个例子吧:

    #ifdef _DEBUG#pragma message

    ("编译连接为调试模式...")#endif // _DEBUG

     

     

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示

    编译器完成一些特定的动作。#pragma
    指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有

    的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
    其格式一般为: #Pragma Para
    其中Para 为参数,下面来看一些常用的参数。

    (1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗
    口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
    #Pragma message(“消息文本”)
    当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
    当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设

    置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源

    代码的什么地方定义了

    _X86这个宏可以用下面的方法
    #ifdef _X86
    #Pragma message(“_X86 macro activated!”)
    #endif
    当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_
    X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了

    (2)另一个使用得比较多的pragma参数是code_seg。格式如:
    #pragma code_seg( ["section-name"[,"section-class"] ] )
    它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

    (3)#pragma once (比较常用)
    只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,

    但是考虑到兼容性并没有太多的使用它。

    (4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加

    快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。
    有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用

    #pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的

    大小先后编译。

    (5)#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体
    外观的定义。

    (6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )
    等价于:
    #pragma warning(disable:4507 34) // 不显示4507和34号警告信息
    #pragma warning(once:4385) // 4385号警告信息仅报告一次
    #pragma warning(error:164) // 把164号警告信息作为一个错误。
    同时这个pragma warning 也支持如下格式:
    #pragma warning( push [ ,n ] )
    #pragma warning( pop )
    这里n代表一个警告等级(1---4)。
    #pragma warning( push )保存所有警告信息的现有的警告状态。
    #pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告
    等级设定为n。
    #pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的
    一切改动取消。例如:
    #pragma warning( push )
    #pragma warning( disable : 4705 )
    #pragma warning( disable : 4706 )
    #pragma warning( disable : 4707 )
    //.......
    #pragma warning( pop )
    在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)。
    (7)pragma comment(...)
    该指令将一个注释记录放入一个对象文件或可执行文件中。
    常用的lib关键字,可以帮我们连入一个库文件。



    #pragma comment( comment-type [,"commentstring"] )

    comment-type是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker之一。
    commentstring是一个提供为comment-type提供附加信息的字符串,
    Remarks:
    1、compiler:放置编译器的版本或者名字到一个对象文件,该选项是被linker忽略的。
    2、exestr:在以后的版本将被取消。
    3、lib:放置一个库搜索记录到对象文件中,这个类型应该是和
    commentstring(指定你要Liner搜索的lib的名称和路径)
    这个库的名字放在Object文件的默认库搜索记录的后面,linker搜索这个这个库就像你在命令行输入这个命令一样。你可以
    在一个源文件中设置多个库记录,它们在object文件中的顺序和在源文件中的顺序一样。如果默认库和附加库的次序是需要
    区别的,使用Z编译开关是防止默认库放到object模块。
    4、linker:指定一个连接选项,这样就不用在命令行输入或者在开发环境中设置了。
    只有下面的linker选项能被传给Linker.
    • /DEFAULTLIB

    • /EXPORT

    • /INCLUDE

    • /MANIFESTDEPENDENCY

    • /MERGE

    • /SECTION

    (1)/DEFAULTLIB:library

    /DEFAULTLIB 选项将一个 library 添加到 LINK 在解析引用时搜索的库列表。用 /DEFAULTLIB 指定的库在命令行上指定的库之后和 .obj 文件中指定的默认库之前被搜索。

    忽略所有默认库 (/NODEFAULTLIB) 选项重写 /DEFAULTLIB:library。如果在两者中指定了相同的 library 名称,忽略库 (/NODEFAULTLIB:library) 选项将重写 /DEFAULTLIB:library

    (2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

    使用该选项,可以从程序导出函数,以便其他程序可以调用该函数。也可以导出数据。通常在 DLL 中定义导出。entryname 是调用程序要使用的函数或数据项的名称。ordinal 在导出表中指定范围在 1 至 65,535 的索引;如果没有指定 ordinal,则 LINK 将分配一个。NONAME 关键字只将函数导出为序号,没有 entryname

    DATA 关键字指定导出项为数据项。客户程序中的数据项必须用 extern __declspec(dllimport) 来声明。
    有三种导出定义的方法,按照建议的使用顺序依次为:

    1. 源代码中的 __declspec(dllexport)

    2. .def 文件中的 EXPORTS 语句

    3. LINK 命令中的 /EXPORT 规范

    所有这三种方法可以用在同一个程序中。LINK 在生成包含导出的程序时还创建导入库,除非生成中使用了 .exp 文件。
    LINK 使用标识符的修饰形式。编译器在创建 .obj 文件时修饰标识符。如果 entryname 以其未修饰的形式指定给链接器(与其在源代码中一样),则 LINK 将试图匹配该名称。如果无法找到唯一的匹配名称,则 LINK 发出错误信息。当需要将标识符指定给链接器时,请使用 Dumpbin 工具获取该标识符的修饰名形式。

    (3)/INCLUDE:symbol

    /INCLUDE 选项通知链接器将指定的符号添加到符号表。

    若要指定多个符号,请在符号名称之间键入逗号 (,)、分号 (;) 或空格。在命令行上,对每个符号指定一次 /INCLUDE:symbol。
    链接器通过将包含符号定义的对象添加到程序来解析 symbol。该功能对于添包含不会链接到程序的库对象非常有用。用该选项指定符号将通过 /OPT:REF 重写该符号的移除。



    我们经常用到的是#pragma   comment(lib,"*.lib")这类的。
    #pragma   comment(lib,"Ws2_32.lib")表示链接Ws2_32.lib这个库。   
    和在工程设置里写上链入Ws2_32.lib的效果一样,不过这种方法写的   
    程序别人在使用你的代码的时候就不用再设置工程settings了
  • 相关阅读:
    hdu5728 PowMod
    CF1156E Special Segments of Permutation
    CF1182E Product Oriented Recurrence
    CF1082E Increasing Frequency
    CF623B Array GCD
    CF1168B Good Triple
    CF1175E Minimal Segment Cover
    php 正则
    windows 下安装composer
    windows apache "The requested operation has failed" 启动失败
  • 原文地址:https://www.cnblogs.com/dplearning/p/3965103.html
Copyright © 2011-2022 走看看