L19#pragma

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    b
    S1的内存布局:11**,1111,
    
                c    S1.a S1.b     d
    S2的内存布局:1***,11**,1111,****11111111
    

猜你喜欢

转载自blog.csdn.net/shouzhoudd/article/details/46352255