脚本宝典收集整理的这篇文章主要介绍了【C】 24_#pragma 使用分析,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
PRagma 简介
一般用法:
'#pragma parameter'
注: 不同的 parameter 参数语法和意义各不相同
C 语言预留给编译器厂商的扩展指示字
pragma message
- message 参数在大多数的编译器中都有相似的实现
- message 参数在编译时输出消息到编译输出窗口中
- message 用于条件编译中可提示代码的版本信息
#if defined(ANDROID20)
#pragma message("Compile Android SDK 2.0 ...")
#define VERSION "Android 2.0"
#endif
与 #error 和 #warning 不同,#pragma message 仅仅代表一条编译消息,不代表程序错误。
实例分析: #pragma message 使用示例
#include <stdio.h>
#if defined(ANDROID20)
#pragma message("Compile Android SDK 2.0 ...")
#define VERSION "Android 2.0"
#elif defined(ANDROID23)
#pragma message("Compile Android SDK 2.3 ...")
#define VERSION "Android 2.3"
#elif defined(ANDROID40)
#pragma message("Compile Android SDK 4.0...")
#define VERSION "Android 4.0"
#else
#error Compile Version is not provided!
#endif
int main()
{
printf("%sn", VERSION);
return 0;
}
编译输出:
[GCC] test.c:10: note: #pragma message: Compile Android SDK 4.0...
[VC] Compile Android SDK 4.0...
运行输出:
[GCC] Android 4.0
[VC] Android 4.0
pragma once
- #pragma once 用于保证头文件只被编译一次
- #pragma once 是编译器相关的,不一定被支持
#ifndef _HEADER_H_
#define _HEADER_H_
// source code
#endif
与
#pragma once
这两种方式有什么区别呢?
- #ifndef 为 C 语言支持,实质包含了多次,通过宏来决定是否选择是否嵌入到源代码中,预处理器处理多次,保证只“嵌入一次”。
- #pragma once 为编译器支持,是真正的只编译一次,之后遇到此文件,直接不做处理。
- #pragma once 具有更高的编译效率。
示例分析: #pragma once 使用分析
Test.c
#include <stdio.h>
#include "global.h"
#include "global.h"
int main()
{
printf("g_value = %dn", g_value);
return 0;
}
global.h
#pragma once
int g_value = 1;
输出:
g_value = 1
VC GCC : 无警告,无错误 【主持】
BCC : 编译出错, g_value多次定义 【不支持】
- 兼顾移植性与编译效率的方法
#ifndef _HEADER_H_
#define _HEADER_H_
#pragma once
// source code
#endif
pragma pack
-
什么是内存对齐
- 不同类型的数据在内存中按照一定的规则排列
- 而不一定是顺序的一个接一个的排列
struct test1
{
char c1;
short s2;
char c2;
int i;
};
struct test2
{
char c1;
char c2;
short s2;
int i;
};
Test1 和 Test2 所占的内存空间是否相同?
sizeof(struct Test1) = 12
sizeof(struct Test2) = 8

为什么需要内存对齐?
未对齐造成两次内存读取【32位机器的读写最小粒度4字节】

#pragma pack 能够改变编译器的默认对齐方式
#pragma pack(1)
struct Test1
{
char c1;
short s2;
char c2;
int i;
};
#pragma pack()
#pragma pack(1)
struct Test2
{
char c1;
char c2;
short s2;
int i;
};
#pragma pack()
sizeof(struct Test1) = 8
sizeof(struct Test2) = 8
struct 占用的内存大小
- 第一个成员起始于 0 偏移处
-
每个成员按其类型大小和pack参数中较小的一个进行对齐
- 偏移地址必须能被对齐参数整除
- 结构体成员的对齐参数大小取其内部pack参数与内部长度最大的数据成员之间较小的作为其对齐参数大小
- 结构体总长度必须为所有对齐参数的整数倍
编译器默认情况下按照 4 字节对齐
编程实验: 结构体大小计算
Test_1.c
#include <stdio.h>
#pragma pack(2)
struct Test1
{ // 对齐参数 偏移地址 大小
char c1; // 1 0 1
short s2; // 2 2 2
char c2; // 1 5 2
int i; // 2 6 4
};
#pragma pack()
#pragma pack(4)
struct Test2
{ // 对齐参数 偏移地址 大小
char c1; // 1 0 1
char c2; // 1 1 1
short s2; // 2 2 2
int i; // 4 4 4
};
#pragma pack()
int main()
{
printf("%dn", sizeof(struct Test1));
printf("%dn", sizeof(struct Test2));
}
输出:
10
8
Test_2.c
#include <stdio.h>
#pragma pack(8)
struct S1
{ // 对齐参数 偏移地址 大小
short s; // 2 0 1
long b; // 4 4 4
}; // 整体长度为所有对齐参数的整数倍, len = 4 + 4 = 8
struct S2
{ // 对齐参数 偏移地址 大小
char c; // 1 0 1
struct S1 d; // 4 4 8
double e; // 8 16 8
}; // 整体长度为所有对齐参数的整数倍 , len = 8 + 16 = 24
#pragma pack()
int main()
{
printf("%dn", sizeof(struct S1));
printf("%dn", sizeof(struct S2));
}
输出:[GCC]
8
20 【截至2018/12/04,GCC 暂不支持8字节对齐,忽略pack(8),默认4字节对齐】
输出:[VC]
8
20
小结
- #pragma 用于指示编译器完成一些特定的动作
-
#pragma 所定义的很多指示字都是编译器特有的
- #pragma message 用于自定义编译消息
- #pragma once 用于保证头文件只被编译一次
- #pragma pack 用于指定内存对齐方式
以上是脚本宝典为你收集整理的【C】 24_#pragma 使用分析全部内容,希望文章能够帮你解决【C】 24_#pragma 使用分析所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。