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. Function.prototype.apply.call

    我们先从一道简单的题目开始,前几天在git上看到的: 定义log方法,它可以代理console.log的方法.log(1,2,3)  =>  1 2 3 通常,你的答案会是这样的: functi ...

  2. Oracle更新表字段时内容中含有特殊字符&的解决方法

    今天在做 Oracle表字段更新时出现了特殊字符&,导致无法更新. 这个问题是第二次碰到了,所以在此记录下,以备后用. 举例: update t set col1='A&B' wher ...

  3. Spark Mllib里的分布式矩阵(行矩阵、带有行索引的行矩阵、坐标矩阵和块矩阵概念、构成)(图文详解)

    不多说,直接上干货! Distributed  matrix : 分布式矩阵 一般能采用分布式矩阵,说明这数据存储下来,量还是有一定的.在Spark Mllib里,提供了四种分布式矩阵存储形式,均由支 ...

  4. HATEOAS REST Service

    用户通过点击页面的href的链接地址,而跳转到其他网页,实现浏览网页的过程了. -> 让调用REST的api就可以实现,类似于用户浏览网页的从一个页面跳转到另外一个页面的过程了 -> 而这 ...

  5. sqlserver跟据当天年月日日期查询数据库当天数据

    select * from Client where  CONVERT(varchar(100), Cli_Datetime, 23) ='2017-11-06' 在查询之前要对表中datetime类 ...

  6. 部署WebService服务碰到的一个小问题

    在部署WebService服务到IIS上之后,发现一直无法在浏览器访问到编写的asmx文件,一直提示404或403错误.提示当前访问的文件时脚本文件. 1.首先检查了在IIS上部署WebService ...

  7. dos 删除文件夹 rd

    windows普通方法删除不了文件.文件夹?那么试试dos命令吧. rd的另外一个写法是rmdir,源自ReMakeDirectory.使用的方法也很简单:rd 文件夹名 即可,例如:rd test. ...

  8. SAP CRM Survey调查问卷的存储模型

    数据库表CRM_SVY_DB_SVS,通过如下的函数CRM_SVY_DB_SVS_CREATE插入: 可以通过指定的创建者和创建时间很容易查找到特定的Survey: 调查问卷的答案明细以XML的格式存 ...

  9. Red Hat Enterprise Linux(RHEL)中yum的repo文件详解

    Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服务器自动下载 ...

  10. UVA 177 PaperFolding 折纸痕 (分形,递归)

    著名的折纸问题:给你一张很大的纸,对折以后再对折,再对折……每次对折都是从右往左折,因此在折了很多次以后,原先的大纸会变成一个窄窄的纸条.现在把这个纸条沿着折纸的痕迹打开,每次都只打开“一半”,即把每 ...