1 pragma 简介
-
#pragma
用于指示编译器完成一些特定的动作 -
#pragma
所定义的很多指示字是编译器独有的 -
#pragma
在不同的编译器间是不可移植的- 预处理器将忽视它所不认识的
#pragma
指令 - 不同的编译器可能以不同的方式解释同一条
#pragma
指令
- 预处理器将忽视它所不认识的
-
一般用法
- 不同的 parameter 参数语法和意义各不相同
#pragma parameter
2 #pragma message
-
message 参数在大多数的编译器中都有相似的实现
-
message 参数在编译时输出消息到编译输出窗口
-
message 用于条件编译中可提示代码的版本信息
-
与
#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("%s ", VERSION); return 0; } //编译:gcc -DANDROID40 test.c -o test test.c:10: note: #pragma message: Compile Android SDK 4.0... //运行结果 Android 4.0
3 #pragma once
-
#pragma once
用于保证头文件只被编译一次 -
#pragma once
是编译器相关的,不一定被支持 -
#pragma once
使用示例#include <stdio.h> #include "global.h" #include "global.h" int main() { printf("g_value = %d ", g_value); return 0; } //global.h #pragma once int g_value = 1;
4 #pragma back
-
内存对齐
- 不同类型的数据在内存中按照一定的规则排列,而不一定是顺序的一个接一个的排列
#include <stdio.h> struct Test1 { char c1; short s; char c2; int i; }; struct Test2 { char c1; char c2; short s; int i; }; int main() { printf("sizeof(Test1) = %d ", sizeof(struct Test1)); //12 printf("sizeof(Test2) = %d ", sizeof(struct Test2)); //8 return 0; }
-
为什么需要内存对齐?
- CPU对内存的读取不是连续的,而是分成块读取的,块的大小只能是1,2,4,8,16...字节
- 当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣
- 某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则会产生硬件异常
-
#pragma back
用于指定内存对齐方式,能够改变编译器的默认对齐方式 -
strcut 占用的内存大小
-
第一个成员起始于 0 偏移处
-
每个成员按其类型大小和 pack 参数中较小的一个进行对齐
- 偏移地址必须能被对齐参数整除
- 结构体成员的大小取其内部长度最大的数据成员作为其大小(仅在计算对齐参数比较时)
-
结构体总长度必须为所有对齐参数的整数倍
-
-
编译器在默认情况下按照 4 字节对齐
-
GCC 不支持
#pragma pack(8)
-
结构体大小计算
- Demo1
#include <stdio.h> #pragma pack(2) struct Test1 { //对齐参数 偏移地址 大小 char c1; //1 0 1 short s; //2 1—>2 2 char c2; //1 4 1 int i; //2 5->6 4 }; #pragma pack() #pragma pack(4) struct Test2 { char c1; char c2; short s; int i; }; #pragma pack() int main() { printf("sizeof(Test1) = %d ", sizeof(struct Test1)); // printf("sizeof(Test2) = %d ", sizeof(struct Test2)); // return 0; }
- Demo2
#include <stdio.h> #pragma pack(8) //8字节 struct S1 { //对齐参数 偏移地址 大小 short a; //2 0 2 long b; //4 2->4 4 }; //24字节 struct S2 { //对齐参数 偏移地址 大小 char c; //1 0 1 struct S1 d; //4 1->4 8 double e; //8 12->16 8 }; #pragma pack() int main() { printf("%d ", sizeof(struct S1)); printf("%d ", sizeof(struct S2)); return 0; }