C语言学习篇(3)-内存编址和对齐
今天小编给各位分享attribute的知识,文中也会对其通过C语言学习篇(3)-内存编址和对齐和C语言输出怎么对齐等多篇文章进行知识讲解,如果文章内容对您有帮助,别忘了关注本站,现在进入正文!
内容导航:
一、C语言学习篇(3)-内存编址和对齐
各个位宽内存示意图内存构造就如同一个大盒子,划分一块块等大小的小格子(单位为8bit,即1byte),每个格子有一个编号,这个编号就是内存地址,这个内存地址(一个数字)和这个格子的空间(实质是一个空间)是一一对应且永久绑定的。这就是内存编址,且以字节为单位的。
内存和数据类型的关系C语言中的基本数据类型有:char short int long float double
而一般int整形类型,与CPU本身的数据位宽是一样(8位,16位单片机int可能是16位,跟编译器有关)。如32位CPU,通常int就是32位,64位CPU,int通常就是64位。
这里就会引出一个思考:数据类型和内存的关系?
数据类型是用来定义变量的,而这些变量需要存储、运算在内存中。所以数据类型必须和内存相匹配才能获得最好的性能,否则可能不工作或者效率低下。
在32位系统中定义变量最好用int,因为这样效率高。原因就在于32位的系统本身配合内存等也是32位,这样的硬件配置天生适合定义32位的int类型变量,效率最高。也能定义8位的char类型变量或者16位的short类型变量,但是实际上访问效率不高。
在很多32位环境下,我们实际定义bool类型变量(实际只需要1个bit就够了)都是用int来实现bool的。也就是说我们定义一个bool b1;时,编译器实际帮我们分配了32位的内存来存储这个bool变量b1。编译器这么做实际上浪费了31位的内存,但是好处是效率高。因此考虑效率或节省内存,大家可根据实际情况,选择适合的数据类型。
内存对齐首先我们这里先简单介绍下,内存对齐,之后有机会讲解结构体的时候,再详细分析。
假如我们定义数据char a, int b, 那数据a,b在内存中是如何分布的呢? 这里分析几个内存对齐情况:
1字节对齐:
2字节对齐:
4字节对齐:
说明: 黄色为数据a的内存分布, 绿色为数据b的内存分布
内存对齐设置#pragma是用来指挥编译器,或者说设置编译器的对齐方式的。编译器的默认对齐方式是4,但是有时候我不希望对齐方式是4,而希望是别的(譬如希望1字节对齐,也可能希望是8,甚至可能希望128字节对齐)。
常用的设置编译器编译器对齐命令有2种:
第一种是#pragma pack(),这种就是设置编译器1字节对齐(有些人喜欢讲:设置编译器不对齐访问,还有些讲:取消编译器对齐访问);
第二种是#pragma pack(4),这个括号中的数字就表示我们希望多少字节对齐。 我们需要#prgama pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数就是n。#prgma pack的方式在很多C环境下都是支持的,但是gcc虽然也可以不过不建议使用。
gcc推荐的指令__attribute__((packed)):取消内存对齐,或者说是1字节对齐 __attribute__((aligned(n))):设定结构体类型整体按n字节对齐,注意是整体而不是这个结构体变量内的元素按n字节对齐
一、C语言输出怎么对齐
#include
#include
intmain()
{
inta,b;
scanf("%d%d",&a,&b);
printf("%s\n","OctalDecimalHexadecimal");
printf("%*o%*d%*x\n%*o%*d%*x",-strlen("Octal"),a,-strlen("Decimal"),a,-strlen("Hexadecimal"),a,-strlen("Octal"),b,-strlen("Decimal"),b,-strlen("Hexadecimal"),b);
return0;
}
二、位字符对齐和C语言对齐是什么?
我知道的C语言需要对齐的地方有两个。一个是int类型的变量,需要分配到4的倍数地址上。
第二个是struct,当不同类型放到一个struct里,为了访问效率高,按最大的类型对齐。所以用sizeof求一个struct占用字节数时,跟单个成员占用字节数加起来不一样。
三、C语言各种存储模式的区别?最常用的存储模式有哪些?
各种存储模式之间有什么区别?DOS用一种段地址结构来编址计算机的内存,每一个物理内存位置都有一个可通过段地址一偏移量的方式来访问的相关地址。为了支持这种段地址结构,大多数C编译程序都允许你用以下6种存储模式来创建程序:
-----------------------------------------------------------------------
存储模式 限制 所用指针
-----------------------------------------------------------------------
Tiny(微) 代码、数据和栈一64KB Near
Small(小) 代码一64KB Near
数据和栈一64KB Near
Medium(中) 代码一1MB Far
数据和栈一64KB Near
Compact(紧缩) 代码一64KB Near
数据和栈一1MB Far
Large(大) 代码一1MB Far
数据和栈一1MB Far
Huge*(巨) 代码一1MB Far
数据和栈一1MB Far
-----------------------------------------------------------------------
*注意:在Huge存储模式下,静态数据(如数组)可以超过64KB,这在其它存储模式下都不行。
Tiny存储模式的限制很严(所有的代码、数据和栈都被限制在64KB中),它通常用来生成"COM"文件。由于内存地址的“安排”方式的限制,Huge模式会带来显著的性能损失,因此它很少被使用。
最常使用的存储模式有哪些?
最常使用的存储模式有Small,Medium和Large这几种。Tiny存储模式一般只用来生成".COM"文件,在现在的高性能计算机上,它已很少被使用了。Compact存储模式允许程序有很少的代码和大量的数据,在今天的商业应用环境中,它同样也不常用了。由于Huge存储模式的存储地址机制导致它的效率较低,所以它也很少被使用。
一般说来,你应该根据程序的大小选用Small,Medium或Large中的一种存储模式。对一个小的实用程序来说,Small存储模式可能是最合适的,这种存储模式允许有64KB的代码和64KB数据和栈。如果程序有更大一些的数据要求,你可以使用Medium存储模式,它允许程序有多达1MB的可寻址数据空间。对于更大的程序,你应该使用Large存储模式,它允许程序有1MB的代码和1MB的数据和栈空间。
如果你在编写一个Windows程序或者在使用一个32位编译程序,那么你最好使用Small存储模式,因为这样的环境并不受DOS程序的段地址结构的限制。
应该使用哪种存储模式?
如果要生成一个“.COM”文件,匦胧褂肨iny存储模式,即所有的代码、数据和栈空间都被限制在64KB中。小的实用程序普遍使用这种存储模式。相对较小的程序也可以使用Small存储模式,只不过不必把整个程序都限制在64KB中。在Small存储模式下,有64KB的代码空间和64KB的数据和栈空间。除了用于小程序外,Small存储模式还可用在Windows或32位编译程序这样的环境中,因为在这些环境中内存寻址并不受DOS中16位的限制。
如果一个程序的代码量相对较大而静态数据量相对较小,你可以用Medium存储模式来创建程序。如果程序很大(需要很多模块,大量的代码和数据),那么你应该选用Large存储模式,这种存储模式常用在DOS下编写商用软件。
与Small,Medium和Large存储模式相比,Compact和Huge存储模式要少用得多。Cornpact存储模式允许程序有大量的静态数据和相对较少(64KB或更少)的代码。满足这种模式的程序很少,常常是一些转移程序,它们有大量必须存到内存中的静态转移表。Huge存储模式与Large存储模式基本相同,只是Huge存储模式允许程序有超过64KB的静态数据。与Compact存储模式相似,Huge存储模式也很少被使用,这主要是因为它会带来显著的性能损失。由于Huge存储模式的执行效率较低,因此你应该避免使用这种模式,除非你确实需要超过64KB的一个数组或其它静态数据。记住,数组和其它程序结构可通过malloc()和calloc()在程序运行时进行动态分配,它们在本质上并不必须是静态的。
关于attribute的问题,通过《位字符对齐和C语言对齐是什么?》、《C语言各种存储模式的区别?最常用的存储模式有哪些?》等文章的解答希望已经帮助到您了!如您想了解更多关于attribute的相关信息,请到本站进行查找!
爱资源吧版权声明:以上文中内容来自网络,如有侵权请联系删除,谢谢。