__attribute__((packed))详解

合集下载

C语言GNU扩展语法

C语言GNU扩展语法

GNU C 9条扩展语法GNC CC是一个功能非常强大的跨平台C编译器,它对标准C语言进行了一系列扩展,以增强标准C的功能,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。

本文把支持GNU扩展的C语言称为GNU C。

Linux内核代码使用了大量的GNU C扩展,以至于能够编译Linux内核的唯一编译器是GNU CC,以前甚至出现过编译Linux内核要使用特殊的GNU CC版本的情况。

本文是对Linux内核使用的GNU C扩展的一个汇总,希望当你读内核源码遇到不理解的语法和语义时,能从本文找到一个初步的解答,更详细的信息可以查看。

文中的例子取自Linux 2.4.18。

1、零长度和变量长度数组组长度为1,分配时计算对象大小比较复杂。

3、语句表达式GNU C把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本只能在复合语句中使用。

例如:复合语句的最后一个语句应该是一个表达式,它的值将成为这个语句表达式的值。

这个定义计算x和y分别两次,当参数有副作用时,将产生不正确的结果,使用语句表达式只计算参数一次,避免了可能的错误。

语句表达式通常用于宏定义。

4、typeof 关键字使用前一节定义的宏需要知道参数的类型,利用typeof可以定义更通用的宏,不必事先这里typeof(x)表示x的值类型,第3行定义了一个与x 类型相同的局部变量_x 并初使化为x,注意第5行的作用是检查参数x和y的类型是否相同。

typeof 可以用在任何类型可以使用的地方,通常用于宏定义。

5、可变参数宏这里arg表示其余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成arg 的值,在宏扩展时替换arg,例如:使用##的原因是处理arg不匹配任何参数的情况,这时arg的值为空,GNU C预处理器在这种特殊情况下,丢弃##之前的逗号,这样扩展为注意最后没有逗号。

gd32单片机attribute用法 -回复

gd32单片机attribute用法 -回复

gd32单片机attribute用法-回复神州数码GD32系列微控制器是由中国的神州数码科技有限公司开发和生产的一类全新的高性能芯片。

其中,attribute(属性)是GD32单片机开发中非常重要的一个关键词。

在本文中,我们将详细介绍GD32单片机attribute的用法,并从基本概念到具体实现进行一步一步的回答。

第一部分:attribute的基本概念在GD32单片机开发中,attribute是一种用于对变量、函数或整个文件进行属性修饰的关键字。

它可以用于指定编译器的行为,以达到优化代码、控制内存布局、调整函数入口等目的。

attribute的语法形式一般为:__attribute__((属性名称))。

在attribute中,属性名称可以用来控制编译器的行为,例如:1. 优化属性:常用的优化属性有inline、noinline、always_inline等。

其中,inline表示将函数作为内联函数进行编译,noinline表示禁止将函数进行内联优化,always_inline表示强制将函数作为内联函数进行编译。

2. 引用属性:常用的引用属性有weak、alias等。

其中,weak表示变量或函数是弱符号,即可以被覆盖或者忽略,alias表示变量或函数取别名。

3. 扩展属性:常用的扩展属性有packed、aligned、section等。

其中,packed表示将结构体或者联合体按最小字节对齐方式进行打包,aligned 表示将结构体或者联合体按指定字节对齐方式进行打包,section表示将变量、函数等放置到指定的数据段或者代码段。

第二部分:attribute的使用方法在GD32单片机开发中,attribute常用于以下几种应用场景:1. 函数内联通过将函数标记为inline属性,可以指示编译器将函数进行内联展开,从而减少函数调用的消耗。

例如:cstatic inline void delay_us(uint32_t nus)__attribute__((always_inline));2. 弱函数和强函数通过将函数标记为weak属性,可以将其定义为弱函数,即如果程序中存在同名的强函数,则弱函数会被覆盖或忽略。

UBIFS分析一:六个区

UBIFS分析一:六个区

UBIFS中六个区详解UBIFS中一共分为六个区,分别为superblock areamaster node areajournal (or log)areaLPT(LEB properties tree) areaOrphan areaThe mian area对于第一个区我不准备做介绍,因为superblock是每一个文件系统必备的。

MASTER AREA:UBIFS为了进行垃圾回收,采用了node结构来进行文件的管理,什么是node?我觉得以UBIFS中的一个inode node来打个比方。

struct ubifs_ino_node {struct ubifs_ch ch;__u8 key[UBIFS_MAX_KEY_LEN];__le64 creat_sqnum;__le64 size;__le64 atime_sec;__le64 ctime_sec;__le64 mtime_sec;__le32 atime_nsec;__le32 ctime_nsec;__le32 mtime_nsec;__le32 nlink;__le32 uid;__le32 gid;__le32 mode;__le32 flags;__le32 data_len;__le32 xattr_cnt;__le32 xattr_size;__u8 padding1[4]; /* Watch 'zero_ino_node_unused()' if changing! */__le32 xattr_names;__le16 compr_type;__u8 padding2[26]; /* Watch 'zero_ino_node_unused()' if changing! */__u8 data[];} __attribute__ ((packed));node就是文件信息和数据的一个结合。

stm32中使用#pragma pack(非常有用的字节对齐用法说明)

stm32中使用#pragma pack(非常有用的字节对齐用法说明)

#pragma pack(4) //按4字节对齐,但实际上由于结构体中单个成员的最大占用字节数为2字节,因此实际还是按2字节对齐typedef struct{char buf[3];//buf[1]按1字节对齐,buf[2]按1字节对齐,由于buf[3]的下一成员word a是按两字节对齐,因此buf[3]按1字节对齐后,后面只需补一空字节word a; //#pragma pack(4),取小值为2,按2字节对齐。

}kk;#pragma pack() //取消自定义字节对齐方式对齐的原则是min(sizeof(word ),4)=2,因此是2字节对齐,而不是我们认为的4字节对齐。

这里有三点很重要:1.每个成员分别按自己的方式对齐,并能最小化长度2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度3.对齐后的结构体整体长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐补充一下,对于数组,比如:char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐.如果写: typedef char Array3[3];Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度.不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个.声明:整理自网络达人们的帖子,部分参照MSDN。

作用:指定结构体、联合以及类成员的packing alignment;语法:#pragma pack( [show] | [push | pop] [, identifier], n )说明:1,pack提供数据声明级别的控制,对定义不起作用;2,调用pack时不指定参数,n将被设成默认值;3,一旦改变数据类型的alignment,直接效果就是占用memory的减少,但是performance会下降;语法具体分析:1,show:可选参数;显示当前packing aligment的字节数,以warning message的形式被显示;2,push:可选参数;将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈;3,pop:可选参数;从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment 数值;如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop 直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略;4,identifier:可选参数;当同push一起使用时,赋予当前被压入栈中的record一个名称;当同pop一起使用时,从internal compiler stack 中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作;5,n:可选参数;指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16。

MDK-ARM armcc编译器——编译器特有的功能

MDK-ARM armcc编译器——编译器特有的功能

Compiler-specific FeaturesChapter 9 Compiler-specific FeaturesDescribes compiler-specific features including ARM extensions to the C and C++ Standards, ARM-specific pragmas and intrinsics, and predefined macros.It contains the following sections:⏹9.1 Keywords and operators.⏹9.2 __align.⏹9.3 __ALIGNOF__.⏹9.4 __alignof__.⏹9.5 __asm.⏹9.6 __forceinline.⏹9.7 __global_reg.⏹9.8 __inline.⏹9.9 __int64.⏹9.10 __INTADDR__.⏹9.11 __irq.⏹9.12 __packed.⏹9.13 __pure.⏹9.14 __smc.⏹9.15 __softfp.⏹9.16 __svc.⏹9.17 __svc_indirect.⏹9.18 __svc_indirect_r7.⏹9.19 __value_in_regs.⏹9.20 __weak.⏹9.21 __writeonly.⏹9.22 __declspec attributes.⏹9.23 __declspec(dllexport).⏹9.24 __declspec(dllimport).⏹9.25 __declspec(noinline).⏹9.26 __declspec(noreturn).⏹9.27 __declspec(nothrow).⏹9.28 __declspec(notshared).⏹9.29 __declspec(thread).⏹9.30 Function attributes.⏹9.31 __attribute__((alias)) function attribute.⏹9.32 __attribute__((always_inline)) function attribute.⏹9.33 __attribute__((const)) function attribute.⏹9.34 __attribute__((constructor[(priority)])) function attribute.⏹9.35 __attribute__((deprecated)) function attribute.⏹9.36 __attribute__((destructor[(priority)])) function attribute.⏹9.37 __attribute__((format_arg(string-index))) function attribute.⏹9.38 __attribute__((malloc)) function attribute.⏹9.39 __attribute__((noinline)) function attribute.⏹9.40 __attribute__((nomerge)) function attribute.⏹9.41 __attribute__((nonnull)) function attribute.⏹9.42 __attribute__((noreturn)) function attribute.⏹9.43 __attribute__((notailcall)) function attribute.⏹9.44 __attribute__((pcs("calling_convention"))) function attribute.⏹9.45 __attribute__((pure)) function attribute.⏹9.46 __attribute__((section("name"))) function attribute.⏹9.47 __attribute__((sentinel)) function attribute.⏹9.48 __attribute__((unused)) function attribute.⏹9.49 __attribute__((used)) function attribute.⏹9.50 __attribute__((visibility("visibility_type"))) function attribute.⏹9.51 __attribute__((weak)) function attribute.⏹9.52 __attribute__((weakref("target"))) function attribute.⏹9.53 Type attributes.⏹9.54 __attribute__((bitband)) type attribute.⏹9.55 __attribute__((aligned)) type attribute.⏹9.56 __attribute__((packed)) type attribute.⏹9.57 Variable attributes.⏹9.58 __attribute__((alias)) variable attribute.⏹9.59 __attribute__((at(address))) variable attribute.⏹9.60 __attribute__((aligned)) variable attribute.⏹9.61 __attribute__((deprecated)) variable attribute.⏹9.62 __attribute__((noinline)) constant variable attribute.⏹9.63 __attribute__((packed)) variable attribute.⏹9.64 __attribute__((section("name"))) variable attribute.⏹9.65 __attribute__((unused)) variable attribute.⏹9.66 __attribute__((used)) variable attribute.⏹9.67 __attribute__((visibility("visibility_type"))) variable attribute.⏹9.68 __attribute__((weak)) variable attribute.⏹9.69 __attribute__((weakref("target"))) variable attribute.⏹9.70 __attribute__((zero_init)) variable attribute.⏹9.71 Pragmas.⏹9.72 #pragma anon_unions, #pragma no_anon_unions.⏹9.73 #pragma arm.⏹9.74 #pragma arm section [section_type_list].⏹9.75 #pragma diag_default tag[,tag,...].⏹9.76 #pragma diag_error tag[,tag,...].⏹9.77 #pragma diag_remark tag[,tag,...].⏹9.78 #pragma diag_suppress tag[,tag,...].⏹9.79 #pragma diag_warning tag[, tag, ...].⏹9.80 #pragma exceptions_unwind, #pragma no_exceptions_unwind.⏹9.81 #pragma hdrstop.⏹9.82 #pragma import symbol_name.⏹9.83 #pragma import(__use_full_stdio).⏹9.84 #pragma import(__use_smaller_memcpy).⏹9.85 #pragma inline, #pragma no_inline.⏹9.86 #pragma no_pch.⏹9.87 #pragma Onum.⏹9.88 #pragma once.⏹9.89 #pragma Ospace.⏹9.90 #pragma Otime.⏹9.91 #pragma pack(n).⏹9.92 #pragma pop.⏹9.93 #pragma push.⏹9.94 #pragma softfp_linkage, #pragma no_softfp_linkage.⏹9.95 #pragma thumb.⏹9.96 #pragma unroll [(n)].⏹9.97 #pragma unroll_completely.⏹9.98 #pragma weak symbol, #pragma weak symbol1 = symbol2.⏹9.99 Instruction intrinsics.⏹9.100 __breakpoint intrinsic.⏹9.101 __cdp intrinsic.⏹9.102 __clrex intrinsic.⏹9.103 __clz intrinsic.⏹9.104 __current_pc intrinsic.⏹9.105 __current_sp intrinsic.⏹9.106 __disable_fiq intrinsic.⏹9.107 __disable_irq intrinsic.⏹9.108 __enable_fiq intrinsic.⏹9.109 __enable_irq intrinsic.⏹9.110 __fabs intrinsic.⏹9.111 __fabsf intrinsic.⏹9.112 __force_stores intrinsic.⏹9.113 __ldrex intrinsic.⏹9.114 __ldrexd intrinsic.⏹9.115 __ldrt intrinsic.⏹9.116 __memory_changed intrinsic.⏹9.117 __nop intrinsic.⏹9.118 __pld intrinsic.⏹9.119 __pldw intrinsic.⏹9.120 __pli intrinsic.⏹9.121 __promise intrinsic.⏹9.122 __qadd intrinsic.⏹9.123 __qdbl intrinsic.⏹9.124 __qsub intrinsic.⏹9.125 __rbit intrinsic.⏹9.126 __rev intrinsic.⏹9.127 __return_address intrinsic.⏹9.128 __ror intrinsic.⏹9.129 __schedule_barrier intrinsic.⏹9.130 __semihost intrinsic.⏹9.131 __sev intrinsic.⏹9.132 __sqrt intrinsic.⏹9.133 __sqrtf intrinsic.⏹9.134 __ssat intrinsic.⏹9.135 __strex intrinsic.⏹9.136 __strexd intrinsic.⏹9.137 __strt intrinsic.⏹9.138 __swp intrinsic.⏹9.139 __usat intrinsic.⏹9.140 __wfe intrinsic.⏹9.141 __wfi intrinsic.⏹9.142 __yield intrinsic.⏹9.143 ARMv6 SIMD intrinsics.⏹9.144 ETSI basic operations.⏹9.145 C55x intrinsics.⏹9.146 VFP status intrinsic.⏹9.147 __vfp_status intrinsic.⏹9.148 Fused Multiply Add (FMA) intrinsics.⏹9.149 Named register variables.⏹9.150 Predefined macros.⏹9.151 Built-in function name variables.Copyright © Keil, An ARM Company. All rights reserved.。

C++__attribute__详解

C++__attribute__详解

C++__attribute__详解1.__attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。

这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows 下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的。

例如:在TC下:struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;(紧凑模式)在GCC下:struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;(非紧凑模式)在GCC下:struct my{ char ch; int a;}__attrubte__((packed)) sizeof(int)=4;sizeof(my)=52.__attribute__关键字主要是用来在函数或数据声明中设置其属性。

给函数赋给属性的主要目的在于让编译器进行优化。

函数声明中的__attribute__((noreturn)),就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码。

GNU C的一大特色就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:__attribute__ ((attribute-list))其位置约束:放于声明的尾部“;”之前。

函数属性(Function Attribute):函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。

C语言中的__attribute__机制

C语言中的__attribute__机制

C语言中的__attribute__机制分类:C/C++2011-10-24 19:53100人阅读评论(0)收藏举报c语言attributesprofiling编译器structGNU C的一大特色(却不被初学者所知)就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:__attribute__ ((attribute-list))其位置约束为:放于声明的尾部“;”之前。

函数属性(Function Attribute)函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。

__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用–Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

下面介绍几个常见的属性参数。

__attribute__ format该__attribute__属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。

该功能十分有用,尤其是处理一些很难发现的bug。

format的语法格式为:format (archetype, string-index, first-to-check)format属性告诉编译器,按照printf, scanf,strftime或strfmon的参数表格式规则对该函数的参数进行检查。

“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。

结构体字节对齐的方法

结构体字节对齐的方法

结构体字节对齐的方法全文共四篇示例,供读者参考第一篇示例:结构体字节对齐是编程中一个非常重要的概念,尤其在涉及到内存对齐的底层编程中更是不可或缺。

在结构体的定义中,每个元素都需要在内存中占用一定的空间,而结构体整体的大小受到字节对齐规则的限制。

本文将介绍结构体字节对齐的方法及其原理,希望能帮助读者更好地理解和掌握这一概念。

一、什么是字节对齐字节对齐是指在结构体中每个元素按照特定的规则分配内存空间,以便提高内存读取的效率。

在计算机系统中,一般要求数据在内存中的存储地址是某个特定值的倍数,这个特定值就是对齐系数。

常用的对齐系数有1、2、4、8等,根据不同的系统和编译器,对齐系数可能会有所不同。

二、结构体字节对齐的原理在C语言中,结构体的内存对齐是通过编译器来进行处理的。

当定义一个结构体时,编译器会按照一定的规则对结构体中的元素进行字节对齐,以便提高读取效率。

具体的对齐规则如下:1. 结构体中每个元素的偏移量必须是它自身类型大小的整数倍。

2. 结构体的大小必须是最大元素类型大小的整数倍。

3. 结构体的对齐系数为结构体中所有元素类型大小的最大值。

通过这些规则,编译器可以在编译时确定结构体的大小,并根据对齐系数进行内存对齐,从而提高内存访问的效率。

1. 使用#pragma pack指令在C语言中,可以使用#pragma pack指令来改变编译器默认的对齐系数。

通过指定pack(n)来设置n值,表示结构体的对齐系数为n。

这样可以在需要的时候自定义结构体的对齐系数,提高程序的效率。

```c#pragma pack(1)struct Student {char name[10];int age;float score;};```上面的代码中,通过#pragma pack(1)改变了结构体的对齐系数为1,从而可以确保结构体中的每个元素都按照一个字节进行对齐。

2. 使用__attribute__((packed))关键字在GCC编译器中,可以使用__attribute__((packed))关键字来实现对齐系数的设置。

MDK5 宏定义CC_ARM

MDK5 宏定义CC_ARM

MDK5 宏定义CC_ARM#if defined (__CC_ARM)这是Keil MDK 里用来识别编译器的宏.__CC_ARM 为Keil 里带的编译器如果定义了(__CC_ARM)启用对匿名结构和联合的支持__CC_ARM1Always set to 1 for the ARM compiler, even when you specify the --thumb option.1.#if defined ( __GNUC__ ) || defined ( __clang__ )2.#ifndef __weak3.#define __weak __attribute__((weak))4.#endif /* __weak */5.#ifndef __packed6.#define __packed __attribute__((__packed__))7.#endif /* __packed */8.#endif /* __GNUC__ */9.10./* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */11.#if defined (__GNUC__) || defined (__clang__) /* GNU Compiler */12.#ifndef __ALIGN_END13.#define __ALIGN_END __attribute__ ((aligned (4)))14.#endif /* __ALIGN_END */15.#ifndef __ALIGN_BEGIN16.#define __ALIGN_BEGIN17.#endif /* __ALIGN_BEGIN */18.#else19.#ifndef __ALIGN_END20.#define __ALIGN_END21.#endif /* __ALIGN_END */22.#ifndef __ALIGN_BEGIN23.#if defined (__CC_ARM) /* ARM Compiler */24.#define __ALIGN_BEGIN __align(4)25.#elif defined (__ICCARM__) /* IAR Compiler */26.#define __ALIGN_BEGIN27.#endif /* __CC_ARM */28.#endif /* __ALIGN_BEGIN */29.#endif /* __GNUC__ */30.31.32./**33. * @brief __RAM_FUNC definition34. */35.#if defined ( __CC_ARM )36./* ARM Compiler37. ------------38. RAM functions are defined using the toolchain options.39. Functions that are executed in RAM should reside in a separate sourcemodule.40. Using the 'Options for File' dialog you can simply change the 'Code /Const'41. area of a module to a memory space in physical RAM.42. Available memory areas are declared in the 'Target' tab of the 'Options for Target'43. dialog.44.*/45.#define __RAM_FUNC HAL_StatusTypeDef46.47.#elif defined ( __ICCARM__ )48./* ICCARM Compiler49. ---------------50. RAM functions are defined using a specific toolchain keyword "__ramfunc".51.*/52.#define __RAM_FUNC __ramfunc HAL_StatusTypeDef53.54.#elif defined ( __GNUC__ ) || defined ( __clang__ )55./* GNU Compiler56. ------------57. RAM functions are defined using a specific toolchain attribute58. "__attribute__((section(".RamFunc")))".59.*/60.#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc")))61.62.#endif63.64./**65. * @brief __NOINLINE definition66. */67.#if defined ( __CC_ARM ) || defined ( __GNUC__ ) || defined ( __clang__ )68./* ARM & GNUCompiler69. ----------------70.*/71.#define __NOINLINE __attribute__ ( (noinline) )72.73.#elif defined ( __ICCARM__ )74./* ICCARM Compiler75. ---------------76.*/77.#define __NOINLINE _Pragma("optimize = no_inline")78.79.#endif80.81.#ifdef __cplusplus82.}83.#endif/* ARM Compiler------------RAM functions are defined using the toolchain options.Functions that are executed in RAM should reside in a separate source module.Using the 'Options for File' dialog you can simply change the 'Code / Const' area of a module to a memory space in physical RAM.Available memory areas are declared in the 'Target' tab of the 'Options for Target' dialog./ * ARM编译器- - - - - - - - - - - -使用工具链选项定义RAM函数。

数据对齐

数据对齐

数据对齐详解一、数据对齐的原因大部分的参考资料都是如是说的:1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。

原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

二、对齐规则每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。

程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16 来改变这一系数,其中的n 就是你要指定的“对齐系数”。

规则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset 为0 的地方,以后每个数据成员的对齐按照#pragma pack 指定的数值和这个数据成员自身长度中,比较小的那个进行。

规则2:结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack 指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

规则3:结合1、2 颗推断:当#pragma pack 的n 值等于或超过所有数据成员长度的时候,这个n 值的大小将不产生任何效果。

三、试验我们通过一系列例子的详细说明来证明这个规则吧!我试验用的编译器包括GCC 3.4.2 和VC6.0 的C 编译器,平台为Windows XP + Sp2。

我们将用典型的struct 对齐来说明。

首先我们定义一个struct:#pragma pack(n) /* n = 1, 2, 4, 8, 16 */struct test_t{int a;char b;short c;char d;};#pragma pack(n)首先我们首先确认在试验平台上的各个类型的size,经验证两个编译器的输出均为:sizeof(char) = 1sizeof(short) = 2sizeof(int) = 4我们的试验过程如下:通过#pragma pack(n)改变“对齐系数”,然后察看sizeof(struct test_t)的值。

gcc的编译属性和选项

gcc的编译属性和选项

gcc的编译属性和选项1.指定内存默认对其参数:__attribute__((packed)):按⼀字节对其__attribute__((aligned(n))):从此之后默认按n字节对其例如:struct stu{ int a; char b;}__attribute__((packed));struct stu{ int a __attribute__((aligned(16))); char b;};例⼦#include <stdio.h>struct ss{char a __attribute__((aligned(16)));int b;//① __attribute__((aligned(16)));};//②__attribute__((aligned(16)));void main(){int i;printf("%d\n", sizeof(struct ss));struct ss s1 = {0x11, 0x55443322};unsigned char *p = (unsigned char *)&s1;for(i=0; i<sizeof(s1); i++){printf("0x%x\n", *(p+i));}}输出:160x110xd10x980x00x220x330x440x550xe00xfc0x980x00xf40xef0x980x0可以看出:__attribute__((aligned(16)))在哪个域后⾯修饰哪个域(注意仅对此域有效,对其它域⽆效),更改了这个域的实际对齐参数,实际对齐参数决定了此域的起始存储位置,再结合结构体的总⼤⼩必须能整除每⼀个域的最⼤对齐参数,因此可以推出来结构体的⼤⼩和内存的存储关系。

将结构体中注释掉掉的部分加上结构体⼤⼩就是32字节。

若只要③处,设定的只是结构体间对齐,结构体成员的存储顺序不变,只是结构体变长了。

C语言字节对齐__align()讲解

C语言字节对齐__align()讲解
五、什么时候需要设置对齐
在设计不同 CPU 下的通信协议时,或者编写硬件驱动程序时寄存器的结构这两个地 方都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生 成的代码不一样.
一、快速理解 1. 什么是字节对齐? 在 C 语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如 int、long、 float 等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在 结构中,编译器为结构的每个成员按其自然边界(alignment)分配空间。各个成员按照它 们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。 为了使 CPU 能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对 齐”. 比如4字节的 int 型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除. 2. 字节对齐有什么作用? 字节对齐的作用不仅是便于 cpu 快速访问,同时合理的利用字节对齐可以有效地节省存储空 间。 对于32位机来说,4字节对齐能够使 cpu 访问速度提高,比如说一个 long 类型的变量,如果 跨越了4字节边界存储,那么 cpu 要读取两次,这样效率就低了。但是在32位机中使用1字节 或者2字节对齐,反而会使变量访问速度降低。所以这要考虑处理器类型,另外还得考虑编 译器的类型。在 vc 中默认是4字节对齐的,GNU gcc 也是默认4字节对齐。 3. 更改 C 编译器的缺省字节对齐方式 在缺省情况下,C 编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地, 可以通过下面的方法来改变缺省的对界条件: · 使用伪指令#pragma pack (n),C 编译器将按照 n 个字节对齐。 · 使用伪指令#pragma pack (),取消自定义字节对齐方式。 另外,还有如下的一种方式: · __attribute((aligned (n))),让所作用的结构成员对齐在 n 字节自然边界上。如果结 构中有成员的长度大于 n,则按照最大成员的长度来对齐。 · __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数 进行对齐。 4. 举例说明 例1 struct test { char x1; short x2; float x3; char x4; }; 由于编译器默认情况下会对这个 struct 作自然边界(有人说“自然对界”我觉得边界更顺 口)对齐,结构的第一个成员 x1,其偏移地址为0,占据了第1个字节。第二个成员 x2为 short 类型,其起始地址必须2字节对界,因此,编译器在 x2和 x1之间填充了一个空字节。结构的 第三个成员 x3和第四个成员 x4恰好落在其自然边界地址上,在它们前面不需要额外的填充 字节。在 test 结构中,成员 x3要求4字节对界,是该结构所有成员中要求的最大边界单元, 因而 test 结构的自然对界条件为4字节,编译器在成员 x4后面填充了3个空字节。整个结构 所占据空间为12字节。 例2 #pragma pack(1) //让编译器对这个结构作1字节对齐

__attribute__((__packed__))

__attribute__((__packed__))

__attribute__((__packed__))⾸先,解释下 “__attribute__ ((__packed__))” 是做什么的?我们知道,通常定义⼀个U32 ,CPU 期望这个 U32 地址是 DW 对齐的, 这样对CPU访问 mem bus ⽐较友好。

所以,当我们定义这样⼀个结构体:struct test{char i,uint32 a}那么,编译器会默认在 i 和 a 之间插⼊ reserve,确保 a 的位置是 4 对齐的。

sizeof(test) = 8.它就等效于:struct test{char i,char reserve[3],uint32 a}加⼊ “__attribute__ ((__packed__))” 的效果,则在于避免编译器 “⾃作聪明”。

告诉编译器,我们这⾥不需要补全。

struct __attribute__ ((__packed__)) test{char i,uint32 a}sizeof(test) = 5; 这会造成 a 地址不对齐,反⽽引⼊⿇烦。

那为什么要有这个东西呢?如下截图,是SPDK⾥⾯关于 SGL 的定义。

我想这个最⼤的好处就是:严格按照(NVMe) SPEC 定义数据结构,避免编译器优化。

也就是说,static 类型的,系统优化会造成通讯或者使⽤错误的,就要加这个类型。

如果只是软件⾃⽤的变量,那最好就不⽤加了,避免出现不对齐的地址,导致性能降低————————————————版权声明:本⽂为CSDN博主「褚道长」的原创⽂章,遵循CC 4.0 BY-SA版权协议,转载请附上原⽂出处链接及本声明。

原⽂链接:https:///zuiyinian/article/details/81174031。

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及⾃然对齐)struct {}node;32为的x86,window下VC下sizeof(node)的值为1,⽽linux的gcc下值为0;⼀、WINDOWS下(VC--其实GCC和其原理基本⼀样,象这种问题,⼀般要查具体的编译器设置)字节对齐的规则:1、⼀般设置的对齐⽅式为1,2,4字节对齐⽅式,VC⼀般默认为4字节(最⼤为8字节)。

结构的⾸地址必须是结构内最宽类型的整数倍地址;另外,结构体的每⼀个成员起始地址必须是⾃⾝类型⼤⼩的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最⾼为4字节对齐),否则在前⼀类型后补0;这⾥特别提到的是数组⼀定要注意,⽽且在⼀些编程的技巧中,我们可以使⽤数组强制字节达到对齐的⽬的。

这在⽹络编程中是很常见的。

举例:⽐如CHAR型占⽤空间为1字节,则其起始位置必须可被1整除。

INT为4字节,其起始位置必须被4带队,依次类推。

(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。

)2、结构体的整体⼤⼩必须可被对齐值整除,默认4(默认,且结构中的类型⼤⼩都⼩于默认的4)。

3、结构体的整体⼤⼩必须可被本结构内的最宽类型整除。

(其实和上⼀条是⼀样的,但这⾥独⽴出来,起注意作⽤。

⽐如结构体⾥的有DOUBLE,那么结构的⼤⼩最后必须可被8整除)注意:GCC不是这样,就是最⾼只能被4整除,它是个死的。

否则(2、3条),编译器会在结构的最后添充⼀定的特定字符来补齐。

struct T{char ch;double d ;};在VC中是16个字节,GCC中为12个字节。

4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,⽽不能以嵌套结构⼤⼩来做为上三种使⽤的基准。

⼆、举例:struct A{int a;char b;short c;};struct B{char b;int a;short c;};struct C{double t;char b;int a;short c;};struct D{char b;double t;int a;short c;};在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;我们先谈第⼀个,(说明⼀下,在考虑结构体⼤⼩时,我们基本可以忽略起始地址的问题,因为这个编译器会⾃动为我们做好,见上⾯的说明),结构体内⾸先是⼀个INT的4字节,起始地址假定为0,整除4,其⼩于等于默认的4字节对齐且0为4(INT的占⽤空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,⼩于4且5为1(CHAR占⽤空间)的整数倍,故占⽤1个字节,然后是⼀个起始地址为5占2个字节的SHORT,其⼩于4,但5不为2的整数倍,故补齐⼀个字节,从第6个字节开始,占2字节空间。

attribute在c语言中的用法

attribute在c语言中的用法

题目:深入探讨attribute在C语言中的用法在C语言中,attribute是一种可以用来修饰变量、函数甚至是类型的特性。

通过添加attribute,可以对代码的行为、性能和存储做出明确的约定,从而提供更灵活的控制和更高的优化。

在本文中,我们将深入探讨attribute在C语言中的用法,以便读者能够更全面、深刻地理解并应用它。

1. attribute的基本概念在C语言中,attribute是由一对双下划线(__)括起来的关键字,用于指定变量或函数的一些特性。

__attribute__((aligned(16)))可以指定一个变量在内存中的对齐方式为16字节。

除了aligned之外,C语言还提供了许多其他的attribute,如noreturn、packed、pure等,它们分别可以用来表示函数没有返回值、结构体紧凑存储、纯函数等特性。

2. attribute的应用场景在实际的C语言编程中,attribute的应用场景非常广泛。

举个例子,我们可以使用__attribute__((deprecated))来标记一个函数或变量已经过时,以便编译器在使用时给出警告。

另外,__attribute__((noinline))可以告诉编译器禁止对某个函数进行内联优化,从而保证该函数一定被调用而不是被内联展开。

3. attribute的灵活性和深度理解通过使用attribute,程序员可以在C语言中实现更细粒度的控制和优化。

我们可以使用__attribute__((hot))来告诉编译器某个函数经常被调用,从而优化其执行速度;也可以使用__attribute__((cold))来告诉编译器某个函数很少被调用,从而减小其代码尺寸。

对attribute的深度理解可以帮助程序员更好地优化代码,提高程序性能。

4. 个人观点与总结在我看来,attribute在C语言中的用法非常有意思,并且非常实用。

通过合理地使用attribute,我们可以更好地控制程序的行为和性能,并且为编译器提供更多的优化提示,从而让我们的代码更加高效、灵活。

__attribute__详解

__attribute__详解

__attribute__详解GNU C的一大特色就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:__attribute__ ((attribute-list))其位置约束为:放于声明的尾部“;”之前。

函数属性(Function Attribute)函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。

__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用–Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

下面介绍几个常见的属性参数。

1.__attribute__ format该__attribute__属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。

该功能十分有用,尤其是处理一些很难发现的bug。

format的语法格式为:format (archetype, string-index, first-to-check)format 属性告诉编译器,按照printf, scanf, strftime或strfmon的参数表格式规则对该函数的参数进行检查。

“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。

具体使用格式如下:__attribute__((format(printf,m,n)))__attribute__((format(scanf,m,n)))其中参数m与n的含义为:m:第几个参数为格式化字符串(format string);n:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几,注意,有时函数参数里还有“隐身”的呢,后面会提到;在使用上,__attribute__((format(printf,m,n)))是常用的,而另一种却很少见到。

__attribute__用法

__attribute__用法

__attribute__用法在C语言中,__attribute__是一种特殊的语法,用于给函数、变量、结构体等对象添加属性。

它可以用于告诉编译器一些额外的信息,帮助编译器进行优化或者进行静态检查。

在本文中,我们将对__attribute__的使用方法进行详细解析,并介绍一些常用的属性。

1. __attribute__((packed))__attribute__((packed))可以用于结构体或者联合体,它告诉编译器不要对结构体进行字节对齐。

在默认情况下,编译器会对结构体进行字节对齐,以提高读写效率。

但是在一些特殊情况下,我们需要按照实际占用的字节数来定义结构体,这时就可以使用packed属性。

例如,我们定义一个结构体来表示一个位域:```struct BitField {unsigned int a : 1;unsigned int b : 2;unsigned int c : 3;} __attribute__((packed));```在上面的例子中,由于使用了packed属性,结构体BitField的大小将是6个字节,而不是按照默认的对齐方式4个字节。

2. __attribute__((aligned(n)))__attribute__((aligned(n)))可以用于变量或者结构体,它告诉编译器将对象对齐到n字节边界。

默认情况下,编译器会按照最大基本类型的大小进行对齐,例如int型变量会按照4字节对齐。

例如,我们定义一个变量,并要求将其对齐到8字节边界:```int var __attribute__((aligned(8)));```在上面的例子中,变量var将被对齐到8字节边界。

3. __attribute__((noreturn))__attribute__((noreturn))用于告诉编译器一个函数不会返回。

这对于一些特殊的函数非常有用,如exit函数、abort函数等。

pragma详解

pragma详解

#pragma详解(一)在#Pragma是预处理指令它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。

#pragma指令对每个编译器给出了一个方法,在保持与C和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。

依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

其格式一般为: #Pragma Para其中Para 为参数,下面来看一些常用的参数。

(1)message 参数。

Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。

其使用方法为:#Pragma message(“消息文本”)当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。

假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法#ifdef _X86#Pragma message(“_X86 macro activated!”)#endif当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated!”。

我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。

(2)另一个使用得比较多的pragma参数是code_seg。

格式如:#pragma code_seg( [\section-name\[,\section-class\] ] )它能够设置程序中函数代码存放的代码段,使用没有section-name字符串的#pragmacode_seg可在编译开始时将其复位,当我们开发驱动程序的时候就会使用到它。

(3)#pragma once (比较常用)只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。

__attribute__机制

__attribute__机制

__attribute__机制xdata uchar dat_tm1818[18][16] _at_ 0x0e00; //成功过__align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)))__align(32):32位对齐__attribute__ :增加变量属性((at(0X68000000))) :变量在存储器中的绝对地址是0X680000001. __attribute__GNU C的一大特色(却不被初学者所知)就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)__attribute__前后都有两个下划线,并且后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数__attribute__语法格式为:__attribute__ ( ( attribute-list ) )函数属性(Function Attribute),函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。

__attribute__机制也很容易同非GNU应用程序做到兼容。

GNU CC需要使用–Wall,这是控制警告信息的一个很好的方式。

下面介绍几个常见的属性参数。

2. format该属性可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。

它可以给被声明的函数加上类似printf或者scanf的特征,该功能十分有用,尤其是处理一些很难发现的bug。

format的语法格式为:format ( archetype, string-index, first-to-check )format属性告诉编译器,按照printf,scanf,strftime或strfmon的参数表格式规则对该函数的参数进行检查。

字节对齐详解

字节对齐详解

字节对齐详解分类:Linux系统编程2009-07-11 10:31 185人阅读评论(0) 收藏举报一.什么是字节对齐,为什么要对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。

一些平台对某些特定类型的数据只能从某些特定地址开始存取。

比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。

比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。

显然在读取效率上下降很多。

二.字节对齐对程序的影响:先让我们看几个例子吧(32bit,x86环境,gcc编译器):设结构体如下定义:struct A{int a;char b;short c;};struct B{char b;int a;short c;};现在已知32位机器上各种数据类型的长度如下:char:1(有符号无符号同)short:2(有符号无符号同)int:4(有符号无符号同)long:4(有符号无符号同)float:4 double:8那么上面两个结构大小如何呢?结果是:sizeof(strcut A)值为8sizeof(struct B)的值却是12结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

__attribute__((packed))详解
(2012-02-24 15:43:38)
转载▼
分类:linux程序
标签:
it
1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。

这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的。

例如:
在TC下:struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;(紧凑模式)
在GCC下:struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;(非紧凑模式)
在GCC下:struct my{ char ch; int a;}__attrubte__ ((packed)) sizeof(int)=4;sizeof(my)=5
2. __attribute__关键字主要是用来在函数或数据声明中设置其属性。

给函数赋给属性的主要目的在于让编译器进行优化。

函数声明中的__attribute__((noreturn)),就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码。

GNU C的一大特色就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:
__attribute__ ((attribute-list))
其位置约束:放于声明的尾部“;”之前。

函数属性(Function Attribute):函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。

__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用–Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

packed属性:使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。

如果你看过GPSR协议在TinyOS中的实现,你一定会注意到下面的语句:
typedef struct {
double x;
double y;
} __attribute__((packed)) position_t;
开始我们还可以理解,不久是定义一个结构体嘛!不过看到后面的语句,你可能就会一头雾水了,’ __attribute__((packed))’是什么东西?有什么作用?一连串的疑问马上就会从你脑袋里冒出来。

虽然这个对理解整个程序没有什么影响,但我不想让这些疑问一直呆在我的脑子里,负担太重。

省得以后念念不忘,而且也许有一天可以用的上呢。

搞清楚这个问题吧!
GNU C的一大特色(却不被初学者所知)就是__attribute__机制。

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__语法格式为:
__attribute__ ((attribute-list))
其位置约束为:放于声明的尾部“;”之前。

packed是类型属性(Type Attribute)的一个参数,使用packed可以减小对象占用的空间。

需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16
字节对齐,那么你此时定义32字节对齐也是无济于事的。

使用该属性对struct或者union类型进行定义,设定其类型的每一个变量的内存约束。

当用在enum类型定义时,暗示了应该使用最小完整的类型(it indicates that the smallest integral type should be used)。

下面的例子中,my-packed-struct类型的变量数组中的值会紧凑在一起,但内部的成员变量s 不会被“pack”,如果希望内部的成员变量也被packed的话,my-unpacked-struct也需要使用packed进行相应的约束。

struct my_unpacked_struct
{
char c;
int i;
};
struct my_packed_struct
{
char c;
int i;
struct my_unpacked_struct s;
}__attribute__ ((__packed__));
在每个系统上看下这个结构体的长度吧。

内存对齐,往往是由编译器来做的,如果你使用的是gcc,可以在定义变量时,添加__attribute__,来决定是否使用内存对齐,或是内存对齐到几个字节,以上面的结构体为例:
1)到4字节,同样可指定对齐到8字节。

struct student
{
char name[7];
uint32_t id;
char subject[5];
} __attribute__ ((aligned(4)));
2)不对齐,结构体的长度,就是各个变量长度的和struct student
{
char name[7];
uint32_t id;
char subject[5];
} __attribute__ ((packed));。

相关文档
最新文档