#pragma once 与 #ifdef

2023-10-27

解析#pragma指令 

在所有的预处理指令中,#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关键字,可以帮我们连入一个库文件。


(8)#pragma pack() 

我们知道在VC中,对于想结构体Struct这样的类型,VC采用8字节对齐的方式,如果我们不想使用8字节对齐(在网络变成中经常需要这样),我们可以在结构体前面加上 

#pragma pack(1) 

struct 

...... 

#pragma pack( )


以下是另一个转载:


在vc6的时代头文件一般使用ifndef define endif

在vc7的时代头文件一般成了pragma once

不知道有没有人深究其中的意义

为什么有这样的代码,是为了头文件不被重复引用,那样编译器抱错的,这两种方法都是同样的目的,有没有区别呢?

还是举例来说明,可能有好几个库,每个库内部可能都有public.h这个文件,如果使用

ifndef public_h

define public_h

...

endif

那么当一个文件同时引用两个这样的库时,后一个库里的文件就不被编译了,而pragma once可以保证文件只被编译一次

看起来pragma once比ifndef define endif要好,那么ifndef define endif

的地方都pragma once好了。今天碰到了又一个例子,比如你有一个zlib.h在几个库都用到,而为了方便,把zlib每个目录下copy了一分,因为这个文件不会作修改,已经很完整了,这个时候如果使用pragma once,就会重复定义,看来ifndef define endif还是又派上用场的地方。

所以对于公有或者接口的文件,使用ifndef define endif,对于内部的文件使用pragma once.


#pragma once 与 #ifndef #define #endif 的区别


对于#pragma once,根据MSDN解说,能够防止一个文件被多次包含。与#ifndef #define #endif形式的文件保护相比,前者是平台相关的,可移植性比较差,但是它效率更高,因为它不需要去打开包含的文件,就可以判断这个文件有没有被包含。当然这个工作是系统帮我们完成的。 

后者的优点在于它是语言相关的特性,所以可移植性好。但是在包含一个文件的时候,只有打开这个文件,根据文件的保护宏是否已经被定义来判断此文件是否已经被包含过。效率相对较低。当然在#i nclude的时候,程序员也可以自己判断所要包含的文件的保护宏是否已经被定义,来决定是否要包含这个文件。类似下面的代码: 

#ifndef FILE_H_

#i nclude "file.h"

#endif

这样作可以得到较高的效率,而且保证可移植性。但是文件之间的依赖性较高,如果一个文件的保护宏改变的话,所有使用如上形式包含这个文件的文件都要修改。有悖于模块化的思想。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/roger_it/archive/2007/02/09/1506249.aspx

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

#pragma once 与 #ifdef 的相关文章

随机推荐

  • 阿里云ecs共享型s6怎么样,带宽操作系统选择区别?

    不错的 基本是一个主流和入门级别的阿里云ecs服务器 满足我们的一般个人和初创企业的建站需求的 价格便宜 性价比高 独立服务器不是和别人共享的 独立公网IP 不影响SEO 共享型实例采用非绑定CPU调度模式 每个vCPU会被随机分配到任何空
  • 如何在MySQL存储过程中保留注释

    如何在MySQL存储过程中保留注释 本来在MySQL的Store Procedure 里添加注释很简单 可惜如果用命令行客户端来导入备份的数据 注释就会被干掉 在存储过程BODY里面添加注释 解决办法 99999 Write your co
  • leetcode第88题“非递减顺序排列“是什么意思?

    我在遇到这个词的时候 确实是影响到了我对题目意思的判断 后来查清楚了 分享 给大家这个小知识点 非递减顺序排列即是指 数列递减 但不是单调递减 中间可以有重复 比如 8 6 6 3 2 1 1 2 3 4 5 递增排列 9 8 7 6 5
  • 如何识别linux是多少位,如何查看linux版本 如何查看LINUX是多少位

    1 查看内核版本命令 1 root q1test01 cat proc version Linux version 2 6 9 22 ELsmp bhcompile crowe devel redhat com gcc version 3
  • js浏览器兼容性的写法

    大致有以下五大类 1 元素查找问题2 DOM操作3 事件4 语法5 XML 一 元素查找问题 1 document all name 1 现有问题 Firefox不支持document all name 2 解决方法 使用getElemen
  • vue3实现卡片翻牌

    vue3实现塔罗牌翻牌 前言 一 操作步骤 1 布局 2 操作 3 样式 总结 前言 最近重刷诡秘之主 感觉里面的塔罗牌挺有意思 于是做了一个简单的塔罗牌翻牌动画 vue3 vite ts 一 操作步骤 1 布局 首先我们定义一个整体的塔罗
  • 基于阿里云服务器+libevent+Qt+mysql+Json等实现仿qq聊天软件

    文章目录 前言 一 在linux上实现服务器端chat server开发 1 1 配置服务器端开发环境 1 2 创建服务器与客户端接口文档 1 3 封装数据库类和链表类 用于存储用户和群聊信息 1 4 封装一个服务器类class Serve
  • XCode 7上传遇到ERROR ITMS-90535 Unexpected CFBundleExecutable Key. 的解决办法

    找到腾讯的info plist 删除箭头指向的一行 重新打包 上传
  • EmbedFire i.MX 6ull开发板学习笔记(八)---使用mfgtools烧录固件

    EmbedFire i MX 6ull开发板学习笔记 八 使用mfgtools烧录固件 一 mfgtools使用介绍 二 改造mfgtools 三 其他问题 之前为了调试方便 一直是将uboot烧录进SD卡 从SD卡启动 然后通过局域网下载
  • 零基础学习OSI七层网络模型

    目录 1 应用层 2 物理层 3 数据链路层
  • angular测试API

    1 resetTestEnvironment 是 Angular 测试中的一个函数 用于重置测试环境 它通常与 initTestEnvironment 和 platformBrowserDynamicTesting 一起使用 以确保在多个测
  • 构建安全的数据访问-威胁与对策(一)

    威胁与对策 要构建安全的数据访问代码 需要了解数据访问代码中的威胁是什么 常见漏洞是如何产生的以及如何使用适当的对策来降低风险 数据访问代码面临的主要威胁包括 SQL 注入 配置数据的泄漏 敏感应用程序数据的泄漏 数据库架构和连接详细信息的
  • 安装配置minicom

    安装配置minicom lsmod grep usbserial 如果直接使用串口线 而没有用到USB转串口设备 此步可以跳过 如果有usbserial 说明系统支持USB转串口 安装minicom Fedora自带有minicom 此步可
  • 永恒之蓝全过程复现

    一 永恒之蓝简介 永恒之蓝是指2017年4月14日晚 黑客团体Shadow Brokers 影子经纪人 公布一大批网络攻击工具 其中包含 永恒之蓝 工具 永恒之蓝 利用Windows系统的SMB漏洞可以获取系统最高权限 5月12日 不法分子
  • 通过IP地址和子网掩码,如何计算出网络地址、广播地址和主机数?

    Q 通过IP地址和子网掩码 如何计算出网络地址 广播地址和主机数 A 知道知道IP地址和子网掩码后 通过 IP地址和子网掩码的 与 运算 可以计算出以下相关地址 1 网络地址 2 广播地址 3 地址范围 4 本网有几台主机 例1 下面例子I
  • 掌握这些GitHub搜索技巧,你的开发效率将翻倍!

    作为开发it行业一员 学习借鉴他人项目是很有必要的 所以我们一般都会从github或者 Gitee 上面去参考借鉴他人的项目来学习增加自己的项目经验 但是一般我还是在github上看项目比较多 毕竟人家实力项目量摆在那里 但是国内访问git
  • 数学实践3 - C++下的稀疏矩阵(Sparse Matrix)迭代求解

    目录 问题描述 稀疏矩阵的迭代求解 算法 Jacobi求解法 原理 收敛性 Konvergenz 终止条件 共轭梯度法 CG Verfahren 原理 收敛性 终止条件 C 下的算法实现 用哈希表储存稀疏矩阵 std unordered m
  • Vue项目不断请求 ‘websocket‘ 问题

    项目 Vue 2 6 10 报错原因 由于我对 Apache 配置了端口转发 www xxx com 至 localhost 8080 因而使得 webpack dev server 出于安全考虑 默认检查 hostname 检查到 hos
  • 在VCenter中进入bash命令行

    一 VCenter开启远程登录 登录VCenter管理地址 https VCIP 5480进入登录界面 输入用户名和密码登录 在访问 访问设置中将ssh登录和bash shell打开 二 远程登录VCenter 用root用户登录VCSA命
  • #pragma once 与 #ifdef

    解析 pragma指令 在所有的预处理指令中 Pragma 指令可能是最复杂的了 它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作 pragma指令对每个编译器给出了一个方法 在保持与C和C 语言完全兼容的情况下 给出主机或操作