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

xiaoxiao2021-02-28  60

#pragma简介#pragma message#pragma once#pragma pack 什么是内存对齐?为什么需要内存对齐?如何进行内存对齐?内存对齐到底是如何计算的呢?

#pragma简介

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

#pragma message

message参数在大多数的编译器中都有相似的实现message参数在编译时输出消息到编译输出窗口中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

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

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

#ifndef _HEADER_FILE_H #define _HEADER_FILE_H //source code #endif

#pragma pack

什么是内存对齐?

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

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

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

为什么需要内存对齐?

CPU对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16…字节当读取操作的数据未对齐,则需要两次总线走起来访问内存,因此性能会大打折扣某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则产生硬件异常

如何进行内存对齐?

#pragma pack用于指定内存对齐方式#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

内存对齐到底是如何计算的呢?

第一个成员起始于0偏移处每个成员按其类型大小和pack参数中较小的一个进行对齐 偏移地址必须能被对齐参数整除结构体成员的大小取其内部长度最大的数据成员作为其大小结构体总长度必须为所有对齐参数的整数倍

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

转载请注明原文地址: https://www.6miu.com/read-2399989.html

最新回复(0)