include的用法,define,pragmma有什么区别

      #pragma once是编译相关,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过现在基本上已经是每个编译器都有这个定义了;

  #ifndef,#define,#endif这个是C++语言相关,这是C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。

     方式一由语言支持所以移植性好,方式二 可以避免名字冲突(详细请看第4点) 

      #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况

  #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

  #pragma once方式产生于#ifndef之后,因此很多人可能甚至没有听说过。目前看来#ifndef更受到推崇。因为#ifndef受语言天生的支持,不受编译器的任何限制;而#pragma once方式却不受一些较老版本的编译器支持,换言之,它的兼容性不够好。也许,再过几年等旧的编译器死绝了,这就不是什么问题了。

  看起来似乎是想兼有两者的优点。不过只要使用了#ifndef就会有宏名冲突的危险,所以混用两种方法似乎不能带来更多的好处,倒是会让一些不熟悉的人感到困惑。

    #endif 这种用法。它们两个有什么区别呢?因为后一种的实现是基于宏参数实现的,所以它每次包含到头文件时便会进去检查,所以效率不高。但是因为是宏参数,所以这是 C 语言支持的,在每个编译器中都会识别。#pragma once  是编译器相关的,它不一定被支持。但是因为编译器一看见它就不去包含了,所以它的效率及其高,因此两种方式各有利弊。我们下来做个试验分析下

        那么下来我们再来看看 C 语言中的内存对齐,什么是内存对齐呢?不同类型的数据在内存中按照一定规则排列,但是不一定是按照顺序的一个接一个的排列。那么为什么需要内存对齐呢?原因有这么几点:1、CPU 对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16 ... 字节;2、当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣;3、某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则会产生异常。#pragma pack 用于指定内存对齐方式

        我们看到两个结构体中的成员变量都一样,但是位置不同。那么问题来了,它们所占的内存大小相同吗?我们来看看编译结果

        很明显结果不一样,那么为什么呢?这就是内存对齐了,在计算机内部,默认的是4字节对齐,因为这样效率最高。我们可以指定它们都是1字节对齐,这样结果就一样了。#pragma pack 能够改变编译器的默认对齐方式,下面给个示例

        那么 struct 占用的内存大小是怎样计算的呢?第一个成员起始于 0 偏移处,每个成员按其类型大小和 pack 参数中较小的一个进行对齐;偏移地址必须能被对齐参数整除,结构体成员的大小取其内部长度最大的数据成员作为其大小;结构体总长度必须为所有对齐参数的整数倍。编译器在默认情况下按照

{ // 内存对齐 起始距离 内存大小 { // 内存对齐 起始距离 内存大小{ // 内存对齐 起始距离 内存大小 { // 内存对齐 起始距离 内存大小

用于指示内存对齐方式。

我要回帖

更多关于 include 的文章

 

随机推荐