C90为预处理指令家族带来一位新成员:#pragma。一般情况下,大家很少见到它。

       #pragma的作用是为特定的编译器提供特定的编译指示,这些指示是具体针对某一种(或某一些)编译器的,其他编译器可能不知道该指示的含义又或者对该指示有不同的理解,也即是说,#pragma的实现是与具体平台相关的。
       为了让大家了解#pragma的用法,这里暂时以HP C Compiler为例子。HP C编译器主要运行在HP-UX平台上,它的一般用法和gcc大致相同,例如要编译程序:
       $cc example.c
       如果我们明确指示编译器优化代码,可以这样编译:
       $cc +On example.c
       其中n可以是1、2、3、4,分别代表不同程度的优化,例如:
       $cc +O2 example.c
       这条命令指示HP C编译器对整个example.c的代码采取第2级别的优化编译。
       但是,某种情况下我们可能需要特殊对待某一部分的代码,譬如暂停优化,HP C编译器提供几种途径去实现,其中之一是使用#pragma:
       //prog.c
       void f(){...}
       #pragma OPTIMIZE OFF
       int g(){...}
       #pragma OPTIMIZE ON
       double h(){...}
       $cc +O2 prog.c
       上面的prog.c中有3个函数,我们想用第2级别的优化编译代码整个文件。惟独函数g()例外,我们出于某种考虑决定不对它进行任何优化,可以看到,用两条#pragma指令就能够达到目的。
       第一条#pragma指令指示编译器停止优化代码,于是g()的代码是没有经过优化的。第二条#pragma指令通知编译器重新开始代码的优化编译(优化级别仍然是先前命令行给出的level 2),所以从h() 开始的代码又都是经过优化的。
       这里以代码的优化编译为例简单介绍了#pragma的用法,读者必须记住:具体的#pragma指令在不同情况下可能有不同的效果。假设有两家厂商各自推出自己的C编译器,可能真会这么巧同时使用相同的#pragma指令,偏偏它们的实现又不相同,这样编译的代码就可能会出现意想不到的结果。所以,为了保证#pragma指令能够被正确的解释,我们通常需要利用其他的预处理指令给予配合,例如:
       ...
       #ifdef __hpux
              #pragma FLOAT_TRAPS_ON _ALL
       #endif
       ...
       上例中,只有定义“__hpux”宏的HP C编译器才会看到#pragma指令,其他编译器,例如gcc,根本不会看到它的,因为gcc不会去定义“__hpux”宏,所以早在预处理阶段,#pragma指令的内容就被预处理程序删掉了。
       有人可能会问:如果万一编译器看到它不认识的#pragma指令会报错吗?
       答案是:不会。
       具体到某一条#pragma指令的涵义不是C标准的管辖范围,编译器不能够因为看到不认识的#pragma指令就说程序有错,惟一的做法是忽略它。
       例如:
       /*Example C code*/
       #pragma UNKNOWN_DIRECTIVE UNKNOWN_OPTION
       int main(void)
       {
              return 0;
       }
       $gcc test.c
       $./a.out
       $
        尽管gcc不认识上面代码中的#pragma指令,但编译test.c是完全没有问题的。
       现在,C99提供新的关键字“_Pragma”完成类似的功能,例如:
       #pragma OPTIMIZE OFF
       在C99中可以写成:
       _Pragma(“OPTIMIZE OFF”)              //注意:语句后面是没有分号的
       “_Pragma”比“#pragma”(在设计上)更加合理,因而功能也有所增强。
       例如,我们的编译器支持4个不同程度的优化等级,如果使用#pragma,则这样写:
       #pragma OPT_LEVEL n //1≤n≤4
    你会不会觉得每次都要重复写“#pragma...”很麻烦?如果可以利用宏定义来简化书写就好了:
    #define OPT_L(x) #pragma OPT_LEVEL x
    这时我们只须写:
    OPT_L(3)
    就相当于写:
    #pragma OPT_LEVEL 3
    可惜,在C90里这永远是一个梦想!因为字符“#”在预处理指令中有特殊的用途,跟在它后面的必须是宏的参数名,例如:
    #define MACRO(x) #x
    那么,MACRO(example)的替换结果为:
    “example”
       可以想象,前面通过#define来定义一个关于#pragma的宏是不可行的。
       不过,新的关键字“_Pragma”就很好的解决了问题,由于_Pragma并不能有字符“#”,所以我们可以放心的定义宏:
       #define OPT_L(X) PRAGMA(OPT_LEVEL X)
       #define PRAGMA(X) _Pragma(#X)
       这时,我们只要写:
       OPT_L(2)
       经过预处理后,就成为:
       _Pragma(“OPT_LEVEL 2”)
       即:
       #pragma OPT_LEVEL 2

#pragma与_Pragma(转载)的更多相关文章

  1. 关于#pragma 和 _pragma

    首先要明确 #pragma 和_Pragma 是什么 这两个都是出自于c/c++ 的 ,其中#pragma 是预处理指令(preProcess directive ) ,#pragma是用来向编译器传 ...

  2. C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)

    因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...

  3. GCC编译器原理(三)------编译原理三:编译过程---预处理

    Gcc的编译流程分为了四个步骤: 预处理,生成预编译文件(.文件):gcc –E hello.c –o hello.i 编译,生成汇编代码(.s文件):gcc –S hello.i –o hello. ...

  4. 1. C++11保证稳定性与兼容性

    1.1 __func__预定义标识符 在c99中,__func__基本功能是返回所在函数的名字,c++11中允许使用在类或结构体中. #include <iostream> using n ...

  5. (转载)关于#pragma pack(push,1)和#pragma pack(1)

    转载http://www.rosoo.net/a/201203/15889.html 一.#pragma pack(push,1)与#pragma pack(1)的区别 这是给编译器用的参数设置,有关 ...

  6. 【转载】#pragma once与#ifndef

    本篇随笔为转载,原贴地址:#pragma once与#ifndef解析 为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式.在 ...

  7. #pragma once 与 #ifndef 解析(转载)

    正在入门驱动编程,遇到一个小问题,如下详细解释. 原文链接:#pragma once 与 #ifndef 解析 http://www.cnblogs.com/hokyhu/archive/2009/0 ...

  8. pragma指令详解(转载)

    #pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注释到对象文件或者可执行文件.comment-type是一个预定义 ...

  9. 转载:C语言的字节对齐及#pragma pack的使用

    C语言的字节对齐及#pragma pack的使用   C编译器的缺省字节对齐方式(自然对界) 在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间. 在结构中,编译器为结构的每个成员 ...

随机推荐

  1. High waits on control file sequential read

    High waits on control file sequential read (文档 ID 2277867.1) In case we run into an issue where cont ...

  2. nodejs 实践:express 最佳实践(五) connect解析

    nodejs 实践:express 最佳实践(五) connect解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需 ...

  3. 一条shell统计代码行数

    Xcode统计代码,用shell命令即可,非常简单.打开终端,进入你的工程目录,执行下列代码 find . -name "*.m" -or -name "*.h" ...

  4. HttpServeletRequest

    一.HttpServeletRequest 接口(javax.servlet.http) 定义:public interface HttpServletRequestextends ServletRe ...

  5. 如何用Windows PowerShell替换命令提示符

    在Windows 10的"开始"按钮中将PowerShell替换为命令提示符,这不是很好吗?我知道你会有疑问,为什么要这样做?可能会失去了运行DOS命令的能力.好吧,让我解释一下. ...

  6. Protocol Buffer学习教程之编译器与类文件(三)

    Protocol Buffer学习教程之编译器与类文件(三) 1. 概述 在前面两篇中,介绍了Protobuf的基本概念.应用场景.与protobuf的语法等.在此篇中将介绍如何自己编译protobu ...

  7. Nginx+Keepalived负载均衡+后端LNMP网站集群

    Centos6.4 x86,4台,地址是10.10.10.11-14,vip给的100,目标是在13和14安装nginx+keepalived,11和12安装nginx+mysql+php,做为web ...

  8. CoreData介绍

    http://blog.csdn.net/zh952016281/article/details/52105683 写在前面 在CoreData中有一些常用的类,称呼可能各不相同.所以这里先约定一些关 ...

  9. java基础—异常处理

    一.异常的概念 异常指的是运行期出现的错误,也就是当程序开始执行以后执行期出现的错误.出现错误时观察错误的名字和行号最为重要.

  10. 性能优化之MySQL优化(慕课)

    MySQL数据库优化 1-1MySQL优化简介 数据库优化的目的 避免出现页面访问错误 由于数据库连接timeout产生5XX错误 由于慢查询造成页面无法加载 由于阻塞造成数据无法提交 增加数据库的稳 ...