C语言#pragma使用方法

本文介绍了C语言中#pragma指令的三种常见用法:自定义编译信息输出、确保头文件仅被包含一次及指定结构体内存对齐方式。通过具体代码示例展示了不同编译器对这些指令的支持情况。

C语言#pragma使用方法

一、总结

       1、#pragma用于指示编译器完成一些特定的动作

       2、#pragma所定义的很多指示字是编译器特有的(每种编译可能都不一样)

              (1) #pragma message 用于自定义编译信息

              (2)#pragma once 用于保证头文件只被编译一次

              (3)#pragama pack用于指定内存对齐(一般用在结构体)

                        struct占用内存大小

                            1)第一个成员起始于0偏移处

                            2)每个成员按其类型大小和pack参数中较小的一个进行对齐

                                     ——偏移地址必须能被对齐参数整除

                                     ——结构体成员的对齐参数(注意是对齐参数,而不是结构体长度)取其内部长度最大的数据成员作为其大小

                            3)结构体总长度必须为所有对齐参数的整数倍

编译器在默认情况下按照4字节对齐

       3、#pragma在不同的编译器间是不可移植的

              (1)预处理器将忽略它不认识#pragma指令

              (2)不同的编译器可能以不同的方式解释同一条#pragma指令

二、代码测试
       1、#pragma message:自定义编译信息输出到终端(一般和#if配合使用,用在控制版本号)
#include <stdio.h>
#define ANDROID20

#if defined ANDROID20
   #pragma message "Compile Android SDK 2.0..."
   #define VERSION "Android 2.0"
#elif defined ANDROID30
   #pragma message "Compile Android SDK 3.0..."
   #define VERSION "Android 3.0"
#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 message信息,运行的时候根本看不见,你们可以通过预处理命令,看下是否在预处理阶段处理了,gcc -E test.c -o test.i  然后找到test.i文件,双击用gedit打开


看见没,预处理根本没处理#pragma message指令,所以#pragma message指令是在编译器处理的

 2、#pragma once:指示编译器头文件被编译一次
#include <stdio.h>
#include "test.h"
#include "test.h"

int main()
{
    printf("g_value = %d\n",g_value);
    return 0;
}

test.h文件内容:

#pragma once

int g_value = 10; 

看下终端输出:


        3、#pragma pack:指定内存对齐
#include <stdio.h>

#pragma pack(2)
struct test1
{                 //对齐参数  偏移地址   大小  
    char c1;      //1          0       1
    char c2;      //1          1       1
    short s;      //2          2       2
    int i;        //2          4       4
};
#pragma pack()

#pragma pack(4)
struct test2
{                 //对齐参数  偏移地址   大小
    char c1;      //1          0       1
    short s;      //2          2       2
    char c2;      //1          4       1
    int i;        //4          8       4
};
#pragma pack()

#pragma pack(8)
struct S1
{                 //对齐参数  偏移地址   大小 
    short s;      //2          0       2
    long l;       //4          4       4
};
struct S2
{                 //对齐参数  偏移地址   大小    
    char c;       //1          0       1
    struct S1 d;  //4          4       8        
    double e;//理论//8         16       8    这里实际是错误的,gcc不支持8字节对齐,所以这里默认是4字节对齐           //实际//4         12       8    所以整个占用内存是20字节 
};
#pragma pack()

int main()
{
    printf("sizeof(struct test1) = %d\n",sizeof(struct test1));  //输出8 
    printf("sizeof(struct test2) = %d\n",sizeof(struct test2));  //输出12
    
    printf("sizeof(struct S1) = %d\n",sizeof(struct S1));        //输出8
    printf("sizeof(struct S2) = %d\n",sizeof(struct S2));        //理论计算应该输出24  但是实际打印输出是20   这是因为gcc不支持8字节内存对齐,所以这里是默认4字节对齐,
    return 0;
}

看下终端打印输出:


程序里面都有注释,所以不讲了

参考资料《狄泰软件C语言进阶》

### C语言 `#pragma` 指令概述 `#pragma` 是一种预处理指令,在C语言编程中被用来向编译器发出特殊的指示。这些指示可以控制某些编译选项或是触发特定行为,但需要注意的是,许多由 `#pragma` 定义的指示词具有编译器专属性质[^2]。 由于不同编译器对于同一 `#pragma` 指令可能存在差异化的解析逻辑,因此这类指令通常不具备跨平台兼容性;当遇到未知或不支持的 `#pragma` 语句时,预处理器会选择跳过而不报错。 ### 基本语法结构 基本形式如下: ```c #pragma 参数名 [参数值] ``` 其中,“参数名”代表具体的功能标识符,而“参数值”则取决于具体的实现需求以及目标编译环境的要求。 ### 实际应用场景举例说明 #### 输出自定义消息 通过使用 `#pragma message` 可以让编译过程中打印指定的信息字符串到标准错误流(通常是命令行界面),这对于调试非常有用。下面是一个简单的例子来展示如何在GCC下应用此功能: ```c // test.c 文件内容 #include <stdio.h> #pragma message ("正在编译test.c...") // 此处会在编译期间显示提示信息 int main(void){ printf("程序运行正常。\n"); return 0; } ``` 当上述源文件被编译时,如果采用 GCC 或者其他支持该特性的工具链,则会看到类似于这样的输出: ``` note: #pragma message: 正在编译test.c... ``` 这表明编译过程顺利,并且成功执行了 `#pragma message` 所设定的操作[^1]。 #### 控制优化级别及其他设置 除了用于发送通知外,`#pragma` 还可用于调整函数级别的优化等级、改变默认调用约定等高级特性。不过这部分内容往往依赖于具体开发环境中所提供的扩展支持情况。 例如,在MSVC (Microsoft Visual Studio Compiler) 中可以通过以下方式临时更改一段代码片段内的优化策略: ```cpp #pragma optimize("", off) void someFunction() { /* 函数体 */ } #pragma optimize("", on) ``` 以上代码段表示关闭针对 `someFunction()` 的所有自动性能改进措施,之后再恢复全局配置中的相应状态。然而值得注意的是,这种做法并不适用于所有的编译系统,开发者应当查阅官方文档确认当前使用的软件版本是否允许此类操作及其确切写法。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值