预编译处理——#pragma使用分析:结构体内存对齐

#pragma简介

  1. #pragma用于指示编译器完成一些特定的动作
  2. #pragma所定义的很多指示字都是编译器特有的
  3. #pragma在不同的编译器间是不可移植
  4. 预处理器将忽略它不认识的#pragma指令
  5. 不同的编译器可能以不同的方式解释同一条#pragma指令
    一般用法:
    #pragma parameter
    注:不同的parama参数语法和意义各不相同。

#pragma message

  1. message参数在大多数的编译器中都有相似的实现
  2. message参数在编译时输出消息到编译输出窗口中
  3. message用于条件编译中可提示代码版本信息
 #if defined(ANDROID20)
      #pragma message("Compile Android SDK 2.0...")
      #define VERSION "Android 2.0"
 #endif

与#error和#warning不同, #pragma message仅仅代表一条编译信息,不代表程序错误。

示例代码:#pragma message使用示例

#include <stdio.h>

#define ANDROID23

#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;
}

输出结果
ctest.c:8: note: #pragma message: Compile Android SDK 2.3…

#pragma once

  1. #pragma once用于保证头文件只被编译一次
  2. #pragma once是编译器相关的,不一定被支持

注:一般我们不使用这种方式,而是使用一下方式:

#ifndef _HEADER_FILE_H
#define _HEADER_FILE_H

//source code

#endif

#pragma pack

什么是内存对齐?

不同类型的数据在内存中按照一定的规则排列
而不一定是顺序的一个接一个的排列。

例如:以下Test1和Test2所占的内存空间是否相同?
Alt text

实际上我们通过代码测试,Test1和Test2所占的内存空间是不相同的。那么它们在内存的分布是怎么样的呢?
Alt text

为什么需要内存对齐?
  1. CPU对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16…字节
  2. 当读取操作的数据未对齐,则需要两次总线走起来访问内存,因此性能会大打折扣
  3. 某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则产生硬件异常
如何进行内存对齐?
  1. #pragma pack用于指定内存对齐方式
  2. #pragma pack能够改变编译器的默认对齐方式

问题:那么sizeof(struct Test1) = ?; sizeof(struct Test2) = ?

示例代码:结构体大小计算

#include <stdio.h>

#pragma pack(2)
struct Test1
{
    char  c1;
    short s;
    char  c2;
    int   i;
};
#pragma pack()

#pragma pack(4)
struct Test2
{
    char  c1;
    char  c2;
    short s;
    int   i;
};
#pragma pack()

int main()
{
    printf("sizeof(Test1) = %d\n", sizeof(struct Test1));
    printf("sizeof(Test2) = %d\n", sizeof(struct Test2));

    return 0;
}

输出结果:
sizeof(Test1) = 10
sizeof(Test2) = 8

内存对齐到底是如何计算的呢?
  1. 第一个成员起始于0偏移处
  2. 每个成员按其类型大小和pack参数中较小的一个进行对齐
    • 偏移地址必须能被对齐参数整除
    • 结构体成员的大小取其内部长度最大的数据成员作为其大小
  3. 结构体总长度必须为所有对齐参数的整数倍

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值