第24课 #pragma 使用分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第24课 #pragma 使用分析相关的知识,希望对你有一定的参考价值。

1. #pragma简介

(1)#pragma用于指示编译器完成一些特定的动作

(2)#pragma所定义的很多指示字是编译器特有的,在不同的编译器间是不可移植的

  ①预处理器将忽略它不认识的#pragma指令

  ②不同编译器可能以不同的方式解释同一条#pragma指令

(3)一般用法:#pragma parameter //注意,不同的parameter参数语法和意义不同。

2. #pragma message——用于自定义编译消息

(1)message参数在大多数的编译器中都有相似的实现

(2)message参数在编译时输出消息到编译输出窗口

(3)message用于条件编译可提示代码的版本信息

(4)与#error和#warning不同,#pragma message仅仅代表一条编译消息,不代表程序错误。

【实例分析】#pragma message使用示例

#include <stdio.h>

#if defined(android20)
    #pragma message("Complie Android SDK 2.0...")
    #define VERSION "Android 2.0"
#elif defined(ANDROID23)
    #pragma message("Complie Android SDK 2.3...")
    #define VERSION "Android 2.3"
#elif defined(ANDROID40)
    #pragma message("Complie Android SDK 4.0...")
    #define VERSION "Android 4.0"
#else
    #error Compile Version is not provided!
#endif

int main()
{
    //可用命令行编译:gcc 24-1.c -DANDROID40
    //在gcc下输出:
    //   24-1.c:10: note: #pragma message: Complie Android SDK 4.0... 
    //在vc\bcc下输出: Complie Android SDK 4.0... 
    printf("%s\n",VERSION); 
    return 0;
}

3. #pragma once——用于保证头文件只被编译一次

(1)#pragma once用于保证头文件只被编译一次

(2)#pragma once是编译器相关的,不一定被支持(vc\gcc都支持,bcc不支持!)

(3)#pragma once比#ifndef…#define…#endif效率高,因为后者定义的头文件仍然会被处理。前者只要头文件被定义一次,就不会再次被处理。

【实例分析】#pragma once使用

 //global.h

#pragma once

int g_nValue = 1;

//说明:因#pragma once不被所有的编译器支持(如bcc不支持),但
//#pragma once又比#ifndef...#define...#endif效率高,如果
//为了让支持#pragma once的编译器有更高的效率有更高的效率,可以采用如下的头文件定义方式

/*
#pragma once   //当编译器不支持#pragma once时,会直接忽略这行

ifndef  _HEADER_FILE_H_
#define _HEADER_FILE_H_

   //source code

#endif
*/

//24-2.c

#include <stdio.h>
#include "global.h"
#include "global.h" //被include两次

int main()
{

    printf("g_nValue = %d \n",g_nValue); 

    return 0;
}

4. #pragma pack——用于指定内存对齐方式

(1)什么是内存对齐

  ①不同类型的数据在内存中按照一定的规则排列

  ②而不一定是顺序的一个接一个的排列。

【】

(2)为什么需要内存对齐?

  ①CPU对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16…字节。

  ②当读取操作的数据未对齐,则需要两次总线周期来访问内存,此性能会大打折扣

  ③某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则产生硬件异常

(3)#pragma pack(n)能够改变编译器的默认对齐方式(默认是按4字节对齐)

  ①struc占用的内存大小

    A.第一个成员起始于0偏移处

    B.每个成员以min(sizeof(成员的类型),n)对齐参数进行对齐。即偏移地址必须能被对齐参数整除,在复合结构体中,某个成员(结构体类型)的大小取其内部长度最大的数据成员作为其大小

  ②结构体总长度必须为所有对齐参数的整数倍

【编程实验】结构体大小计算

 

5. 小结

(1)#pragma用于指示编译器完成一些特定的动作

(2)#pragma所定义的很多指示字是编译器特有的

以上是关于第24课 #pragma 使用分析的主要内容,如果未能解决你的问题,请参考以下文章

#pragma使用分析

第19课 编译过程简介

C之 #pragma(二十二)

#pragma

c ++ - #pragma曾经在不同的操作系统上运行吗?

第10课 struct和union分析