L18: #pragma
- #pragma是编译器指示字,用于指示编译器完成一些特定的工作
- #pragma所定义的很多指示字是编译器和操作系统特有的
- #pragma在不同的编译器之间是不可移植的
#
- 预处指令理器将忽略它不认识的#pragma
- 两个不同的编译器可能以不同的方式解释同一条#pragma指令
- 一般用法:
#pragma parameter
- 不同parameter参数语法和意义各不相同
##
#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\n", VERSION);
return 0;
}
输出相应的信息,在VC中可以输出信息
gcc下编译时没有输出信息
#pragma pack 内存对齐
不同类型的数据在内存中按照一定的规则排列
需要内存对齐的原因
- cpu对内存的读取不是连续的,是分块的,块的大小是1,2,4,8,16字节
- 读取数据未对齐时需要两次总线周期访问内存,性能降低
- 导致一些硬件问题
规则:
- 第一个成员起始于0偏移处
- 每个成员按其类型对齐参数(char:1 short 2等)和指定对齐参数n(默认4)中较小的一个进行对齐
- 偏移地址和成员占用大小均需对齐
- 结构体成员的对齐参数为其所有成员使用的对齐参数的最大值
- 数据存放的起始地址能够除尽对齐参数
- 结构体总长度必须为所有对齐参数的整数倍
//默认4字节对齐时 VC linux下是一样的
#include<stdio.h>
struct test
{
char c1;
short s;
char c2;
int i;
};
int main()
{
printf("%d\n",sizeof(struct test)); //输出12 VC编译环境
return 0;
}
|数据对齐参数|指定对其参数| 变量 |起始地址|大小|实际存储|
|1 | 4 | C1 | 0 |1 |X* |
|2 | 4 | S | 2 |2 |XX |
|1 | 4 | C2 | 4 |1 |X*** |
|4 | 4 | i | 8 |4 |XXXX |
*代表填空,X代表具体数据
面试题
#include <stdio.h>
#pragma pack(8)//gcc 下直接无视 还是按照4字节对齐
struct S1
{
short a; //2
long b; //4
};
struct S2
{
char c;
struct S1 d;
double e;
};
#pragma pack()
int main()
{
struct S2 s2;
printf("%d\n", sizeof(struct S1)); //8(vc) //8(gcc)
printf("%d\n", sizeof(struct S2)); //24(vc) //20(gcc)
printf("%d\n", (int)&(s2.d) - (int)&(s2.c));//4(vc) //4(gcc)
return 0;
}
分析:
- S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
S2 中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是 按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以又添加了4个字节的空(要能整除对齐参数),从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样,一共使用了24个字节.
S1:8字节 |数据对齐参数|指定对其参数| 变量 |起始地址|大小|实际存储 | |2 | 8 |short a | 0 |2 |XX** | |4 | 8 |long b | 4 |4 |XXXX | S2:24字节 |1 | 8 |char c | 8 |1 |X*** | |4 | 8 | s1 d | 12 |8 |XXXXXXXX**** | |8 | 8 |double e | 24 |8 |XXXXXXXX | a b S1的内存布局:11**,1111, c S1.a S1.b d S2的内存布局:1***,11**,1111,****11111111