L19#pragma

来源:互联网 发布:sql注入攻击1r1 编辑:程序博客网 时间:2024/06/06 04:17

L18: #pragma

  1. #pragma是编译器指示字,用于指示编译器完成一些特定的工作
  2. #pragma所定义的很多指示字是编译器和操作系统特有的
  3. #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字节
  • 读取数据未对齐时需要两次总线周期访问内存,性能降低
  • 导致一些硬件问题

规则:

  1. 第一个成员起始于0偏移处
  2. 每个成员按其类型对齐参数(char:1 short 2等)和指定对齐参数n(默认4)中较小的一个进行对齐
    1. 偏移地址和成员占用大小均需对齐
    2. 结构体成员的对齐参数为其所有成员使用的对齐参数的最大值
    3. 数据存放的起始地址能够除尽对齐参数
  3. 结构体总长度必须为所有对齐参数的整数倍
        //默认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;    }

分析:

  1. S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
  2. 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    bS1的内存布局:11**,1111,            c    S1.a S1.b     dS2的内存布局:1***,11**,1111,****11111111
0 0
原创粉丝点击