• 第24课 #pragma使用分析


    #pragma是C语言留给编译器厂商进行扩展用的。

    这个关键字在不同的编译器之间也许是不能够移植的。

    #pragma简介

    #pragma message

    #pragma message打印的消息并不代表代码有什么问题。

    示例:

     1 #include <stdio.h>
     2 
     3 #if defined(ANDROID20)
     4     #pragma message("Compile Android SDK 2.0...")
     5     #define VERSION "Android 2.0"
     6 #elif defined(ANDROID23)
     7     #pragma message("Compile Android SDK 2.3...")
     8     #define VERSION "Android 2.3"
     9 #elif defined(ANDROID40)
    10     #pragma message("Compile Android SDK 4.0...")
    11     #define VERSION "Android 4.0"
    12 #else
    13     #error Compile Version is not provided!
    14 #endif
    15 
    16 int main()
    17 {
    18     printf("%s
    ", VERSION);
    19 
    20     return 0;
    21 }

    编译命令如下:

    可见,在编译期间,预处理器处理#pragma message,并输出信息。

    将上述程序用vc编译器进行编译,结果如下:

    输出和gcc只有略微的差别。

    bcc32的编译输出如下:

    #pragma once

    左边是通过判断宏是否已经定义的方式保证代码只被嵌入一次,预处理器还是处理了这个文件。而#pragma once 保证只处理这个要包含的文件一次。所有pragma once的效率会高一点。

     工程中用的比较多的是ifndef方式,而不是pragma方式,因为并不是所有的编译器都支持pragma once。而ifndef是C语言支持的。

    pragma once使用示例:

    test.c

     1 #include <stdio.h>
     2 #include "global.h"
     3 #include "global.h"
     4 
     5 int main()
     6 {
     7     printf("g_value = %d
    ", g_value);
     8 
     9     return 0;
    10 }

    global.h

    1 #pragma once
    2 
    3 int g_value = 1;

    gcc编译运行结果如下:

    注释掉pragma once后,gcc就会报重定义错误。

    vc2010编译运行结果如下:

    bcc32的编译如下:

    可见bcc并不支持pragma once。预处理器不支持的pragma参数,会直接删除pragma once这一行。

    工程中可以使用以下的解决方案:

    这样可以保证只包含一次,又保证效率。在不支持pragma once的编译器中,还有ifndef做保证。在支持pragma once 的编译器中,它就起作用了,保证文件只被包含一次,也只被处理一次。

    pragma pack:

     示例程序:

    运行结果如下:

    两个结构体的成员是一样的,顺序不一样,占用的空间大小就不一样,这就是内存对齐的结果。

    内存排列的结果:

     内存对齐:

    将上述程序加上pragma pack对齐,如下:

    再次编译运行,结果如下:

    现在两个结构体占用的内存大小就是一样的了。

    再次给出一个示例程序:

     1 #include <stdio.h>
     2 
     3 #pragma pack(8)
     4 
     5 struct S1
     6 {
     7     short a;
     8     long b;
     9 };
    10 
    11 struct S2
    12 {
    13     char c;
    14     struct S1 d;
    15     double e;
    16 };
    17 
    18 #pragma pack()
    19 
    20 int main()
    21 {
    22     printf("%d
    ", sizeof(struct S1));
    23     printf("%d
    ", sizeof(struct S2));
    24 
    25     return 0;
    26 }

    手工分析的对齐结果如下:

    运行结果如下:

    和我们手工计算的结果并不一样。这是因为gcc编译器不支持8字节对齐,在遇到#pragma pack(8)的时候就直接给删除了。然后就按照默认的4字节对齐了。

     在vc编译器下的编译运行结果如下:

    这个运行结果和我们手工分析的一样,说明了不同的编译器对pack中的大小支持也是不一样的。

    小结:

  • 相关阅读:
    线程数究竟设多少合理
    Elasticsearch 技术分析(八):剖析 Elasticsearch 的索引原理
    作为程序员你是如何学习的?
    系统运行缓慢,CPU 100%,以及Full GC次数过多问题的排查思路
    kms相关文档
    删除所有docker容器镜像
    ubuntu mysql5.7安装
    GORM自定义日志配置
    SQL清空全部表数据
    Nginx 证书
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9537245.html
Copyright © 2020-2023  润新知