19-#pragma

来源:互联网 发布:ip地址和端口是什么 编辑:程序博客网 时间:2024/05/16 08:29
#pragma预处理
#pragma是编译器指示字,用于指示编译器完成一些特定的动作
#pragma所定义的很多指示字是编译器和操作系统所独有的
#pragma在不同的编译器间是不可移植的
    预处理器将忽略它不认识的#pragma指令
    两个不同的编译器可能以两种不同的方式解释同一条#pragma指令
一般用法:
    #pragma parameter
注:不同的parameter参数语法和意义各不相同

#pragma message
message参数在大多数的编译器中都有相似的实现
message参数在编译时输出消息到编译输出窗口中
message可用于代码的版本控制
注意:message是VC特有的编译器指示字,GCC中将其忽略;


#include <stdio.h>

/* #define ANDROID23 1 */
#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;
}

#pragma pack
内存对齐
什么是内存对齐?
    不同类型的数据在内存中按照一定的规则排列;而不是顺序的一个挨一个的排放,这就是对齐;
    任何变量的地址必须是P的整数倍.这个规则叫做//数据对齐.
    P取:#pragma pack(n) 指定的字节数(2/4/8/...)和这个变量自身大小二者中的最小值;
    数据对齐会造成结构体内部不同子变量之间有空隙.

    一个结构体变量的大小必须是P的整数倍).这个规则叫//数据补齐.
    P取:#pragma pack(n) 指定的字节数(2/4/8/...)和结构体中最大的子变量二者中的最小值;
    #pragma pack() 默认是4字节
这种补齐可能造成结构体在最后多占用一些浪费的字节.
"结构体中子变量的顺序会影响结构体的大小.
占用空间小的子变量写前边可以节约内存空间.

    struct test1{
        char c1; // 1
        short s; // 2
        char c2; // 1
        int i; // 4
    }
    struct test2{
        char c1; // 1
        char c2; // 1
        short s; // 2
        int i; // 4
    }
test1和test2两种类型所占用的内存空间是否相同?

为什么需要内存对齐?
    CPU对内存的读取是不连续的,而是分成块读取的,块的大小值能是1,2,4,8,16字节;
    当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣;
    某些硬件平台只能从规定的地址处取某些特定类型的数据,否则抛出硬件异常;

#pragma pack能够改变编译器的默认对齐方式
#pragma pack(2) //指定以2字节对齐
#pragma pack(4) //指定以4字节对齐
#pragma pack()  //指定以默认字节(4)对齐

#include <stdio.h>
struct test1{
    char c1;
    short s;
    char c2;
    int i;
}; //12
struct test2{
    char c1;
    char c2;
    short s;
    int i;
}; //8

int main() {
    printf("%d, %d\n", sizeof(struct test1), sizeof(struct test2)); //12, 8
    return 0;
}


#include <stdio.h>
#pragma pack(2)
struct test1{
    char c1;
    short s;
    char c2;
    int i;
}; // 10
struct test2{
    char c1;
    char c2;
    short s;
    int i;
}; // 8
#pragma pack()

int main() {
    printf("%d, %d\n", sizeof(struct test1), sizeof(struct test2)); // 10, 8
    return 0;
}

struct占用内存大小
    每一个成员起始与0偏移处;
    每一个成员按其类型大小和指定对齐参数n中较小的一个进行对齐;
        偏移地址和成员占用大小均需对齐;
        结构体成员的对齐参数为其所有成员使用的对齐参数最大值;
    结构体总长度必须为所有对齐参数的整数倍;


#include <stdio.h>

#pragma pack(8)
#pragma pack(4)
/* #pragma pack(2) */
struct S1 {
    short a; // 2
    long b; // 8
};
struct S2 {
    char c; // 1
    struct S1 d; // 2+8
    double e; // 8
};
#pragma pack()

int main() {
    struct S1 s1;
    struct S2 s2;
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    printf("%p, %p\n", &(s1.a), &(s1.b));
    printf("%p, %p, %p\n", &(s2.c), &(s2.d), &(s2.e));
    printf("%p, %p\n", &(s2.d.a), &(s2.d.b));
    return 0;
}

0 0
原创粉丝点击