内存对齐

C语言内存对齐和结构补齐

我只是一个虾纸丫 提交于 2020-01-21 00:15:25
首先我们先看看下面的C语言的结构体: [cpp] view plain copy typedef struct MemAlign { int a; char b[3]; int c; }MemAlign; 以上这个结构体占用内存多少空间呢?也许你会说,这个简单,计算每个类型的大小,将它们相加就行了,以32为平台为例,int类型占4字节,char占用1字节,所以:4 + 3 + 4 = 11,那么这个结构体一共占用11字节空间。好吧,那么我们就用实践来证明是否正确,我们用sizeof运算符来求出这个结构体占用内存空间大小,sizeof(MemAlign),出乎意料的是,结果居然为12?看来我们错了?当然不是,而是这个结构体被优化了,这个优化有个另外一个名字叫“对齐”,那么这个对齐到底做了什么样的优化呢,听我慢慢解释,再解释之前我们先看一个图,图如下: 相信学过汇编的朋友都很熟悉这张图,这张图就是CPU与内存如何进行数据交换的模型,其中,左边蓝色的方框是CPU,右边绿色的方框是内存,内存上面的0~3是内存地址。这里我们这张图是以32位CPU作为代表,我们都知道,32位CPU是以双字(DWORD)为单位进行数据传输的,也正因为这点,造成了另外一个问题,那么这个问题是什么呢?这个问题就是,既然32位CPU以双字进行数据传输,那么,如果我们的数据只有8位或16位数据的时候

PE之RVA转FOA

我与影子孤独终老i 提交于 2020-01-18 00:05:23
公式 RVA = 内存地址-ImageBase 判断RVA在哪一个节上: RVA>=节n.VirtualAddress RVA<=节n+1.VirtualAddress 偏移=RVA-节n.VirtualAddress FOV=节n.PointerToRawData+偏移 实验-对齐大小一样 #include <stdio.h> char str[] = "ABC"; int main() { printf("Address: %p\n", &str); printf("V: %s\n", str); return 0; } 执行后输出: Address: 00424D8C V: ABC 获取ImageBase ImageBase 在扩展PE头上的第十个属性,基于扩展PE头偏移地址28个字节,大小为DWORD。 00004000,小端存储转十六进制为0x00400000,所以ImageBase的地址为0x00400000。 计算RVA RVA=内存地址-ImageBase=0x00024D8C 获取内存对齐和文件对齐 SectionAlignment 内存对齐 在扩展PE头上的第十一个属性,大小为DWORD。 FileAlignment 文件对齐 在扩展PE头上的第十二个属性,大小为DWORD。 发现内存对齐和文件对齐都是1000h,实验完再找一个对齐不一样的试试。 判断在哪一个节

CUDA ---- Memory Access

与世无争的帅哥 提交于 2020-01-11 21:02:42
Memory Access Patterns 大部分device一开始从global Memory获取数据,而且,大部分GPU应用表现会被带宽限制。因此最大化应用对global Memory带宽的使用时获取高性能的第一步。也就是说,global Memory的使用就没调节好,其它的优化方案也获取不到什么大效果,下面的内容会涉及到不少L1的知识,这部分了解下就好,L1在Maxwell之后就不用了,但是cache的知识点是不变的。 Aligned and Coalesced Access 如下图所示,global Memory的load/store要经由cache,所有的数据会初始化在DRAM,也就是物理的device Memory上,而kernel能够获取的global Memory实际上是一块逻辑内存空间。Kernel对Memory的请求都是由DRAM和SM的片上内存以128-byte和32-byte传输解决的。 所有获取global Memory都要经过L2 cache,也有许多还要经过L1 cache,主要由GPU的架构和获取模式决定的。如果L1和L2都被使用,那么Memory的获取是以128-byte为单位传输的,如果只使用L2,则以32-byte为单位传输,在允许使用L1的GPU中(Maxwell已经彻底不使用L1,原本走L1都换成走texture cache)

c中结构体数据对齐问题

百般思念 提交于 2020-01-10 14:07:34
1.为什么需要数据对齐 提升CPU读取数据的效率。CPU每次都是从以4字节(32位CPU)或是8字节(64位CPU)的整数倍的内存地址中读进数据的(例如32位的只能0x00000004、0x00000008这种地址一次读4字节的数据)。如果数据不对齐,例如一个int类型放在0x00000004、0x00000008这两个内存地址中间,CPU就会多次读取,如果把整形对齐存放在0x00000008就可以一次读取出来。 2.分析(编译器:Dev 电脑:64位) 我们用创建结构体然后用sizeof打印出结构体大小方式来验证数据对齐方式 正式开始,定义一个char和int,如果不对齐sizeof的结果应该是5,看结果 结果是8,将char于int类型补齐,即对char补齐了3个字节。结果是(1+ 3 )+4=8. (注:所有计算试中斜体加粗数据为补齐用) 如果再往后面添加一个数据呢? 依旧会将最后一个char进行数据对齐,结果为(1+ 3 )+4+(1+ 3 )=12 我们将c换到中间去,结果是否还是12呢? 结果变成了8,原因是a和c所需的空间为2,不需要各自补齐3个空间。结果为((1+1)+ 2 )+4=8 那对字符数组呢? 把a[5]直接拆开成5个char类型即可,结果为((1+1+1+1+1)+ 3 )+4=12. 可以做一个小结: 可以发现,

C语言基础--结构体对齐,位域,联合体

末鹿安然 提交于 2020-01-10 03:57:53
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数(alignment modulus)。这种对其限制不仅简化了处理器与存储系统之间的接口的硬件设计,而且提高了存储系统的性能。 2 -- 结构体对齐包括两个方面的含义 1)结构体总长度 2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置 3--不同编译器的对其策略 1)Linux沿用的对其策略是2字节的数据类型(例如short)的地址必须是2的倍数,而更大的数据类型(如int,double)的地址必须是4的倍数。 2)Windows对齐要求更要严格些,任何K字节(基本)对象的地址都必须是k的倍数。 4 -- 结构体大小的计算方法和步骤 1)将结构体内所有数据成员的长度值相加,记为sum_a; 2)将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模式的整数倍; 3)将和sum_b向结构体模数对齐,该模数是#pragma pac指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者。结构体的长度应该是该模数的整数倍.

C 结构体位域

不羁的心 提交于 2020-01-09 20:56:19
位域 : 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。 位段成员必须声明为int、unsigned int或signed int类型(short char long)。 一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为: struct 位域结构名 { 位域列表 }; 其中位域列表的形式为: 类型说明符 位域名:位域长度 例如: struct bs { int a:8; int b:2; int c:6; }; 位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如: struct bs { int a:8; int b:2; int c:6; }data; View Code 说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明: 1. 如果一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域

[go]内存对齐

余生长醉 提交于 2020-01-07 18:29:31
参考 参考-校对版 理解类型的本质 当我使用 C/C++ 编写代码时,理解类型(type)是非常有必要的。如果不理解类型,你就会在编译或者运行代码的时候,碰到一大堆麻烦。无论什么语言,类型都涉及到了编程语法的方方面面。 加强对于类型和指针的理解,对于提高编程水平十分关键。 本文会主要讲解类型。 我们首先来看看这几个字节的内存: 内存地址: FFE4 FFE3 FFE2 FFE1 存储的值: 00000000 11001011 01100101 00001010 请问地址 FFE1 上字节的值是多少? 如果你试图回答一个结果,那就是错的。为什么?因为我还没有告诉你这个字节表示什么。(不同类型的含义不同) 回答 10,那么你又错了。为什么?因为当我说这是数字的时候,你认为我是指十进制的数字。 基数(number base): 所有编号系统(numbering system)要发挥作用,都要有一个基(base)。 从你出生的时候开始,人们就教你用基数 10 来数数了。 这可能是因为我们大多数人都有 10 个手指和 10 个脚趾。另外,用基数 10 来进行数学计算也很自然。 基定义了编号系统所包含的符号数。基数 10 会有 10 个不同的符号,用以表示我们可以计量的无限事物。 基数 10 的编号系统为 0、1、2、3、4、5、6、7、8、9。一旦超过了 9,我们需要增加数的长度。 例如

c语言 printf格式化输出

こ雲淡風輕ζ 提交于 2020-01-06 05:32:48
#include <iostream> #include<stdio.h> #include <cstring> using namespace std; int main() { char c_test[20] = {"1234567890"}; double d_test = 12321; printf("|%-15s|\n",c_test); //左对齐,15位长度,不够补空格 |1234567890 | printf("|%15s|\n",c_test); //右对齐,15位长度,不够补空格 | 1234567890| printf("|%015d|\n",d_test); //右对齐,15位长度,不够补0 |000000304558080| printf("|%-15.2f|\n",d_test);//左对齐,15位长度,带两位小数,不够补空格 |12321.00 | return 0; } 参数 %a 浮点数、十六进制数字和p-记数法(C99) %A    浮点数、十六进制数字和p-记法(C99) %c     一个字符(char) %C 一个ISO宽字符 %d    有符号十进制整数(int) %f     单精度浮点数(默认float)、十进制记数 法( %.nf 这里n表示精确到小数位后n位.十进制计数) %g    根据数值不同自动选择%f或%e. %G   

C语言 结构体对齐

你说的曾经没有我的故事 提交于 2020-01-01 14:29:56
结构体本来应该占用1(char)+4(int)=5个字节,但是为了对齐,实际上占了1(char)+3(补充)+4(int)=8个字节 这是因为计算机读取数据时,一般标准化4个字节读取,为了节约时间,牺牲3个字符大小的内存,以空间换时间 # pragma warning(disable:4996) # include <stdio.h> struct test { char a ; int b ; } ; int main ( int argc , char * argv [ ] ) { struct test a = { 'a' , 1 } ; struct test * p = & a ; printf ( "结构体内存空间:%d字节,起始地址:%x,结束地址:%x\n" , sizeof ( struct test ) , p , p + sizeof ( struct test ) ) ; system ( "pause" ) ; return 0 ; } 参考: https://www.jianshu.com/p/f47e1fadb78e 来源: CSDN 作者: Claroja 链接: https://blog.csdn.net/claroja/article/details/103714766

IOS-内存对齐

混江龙づ霸主 提交于 2019-12-30 20:18:15
一. 内存对齐是什么? 在计算机中,内存大小的基本单位是字节,理论上来讲,可以从任意地址访问某种基本数据类型。 但是实际上,计算机并非按照字节大小读写内存,而是以2、4、8的倍数的字节块来读写内存。因此,编译器会对基本数据类型的合法地址作出一些限制,即它的地址必须是2、4、8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。 在iOS开发过程中,编译器会自动的进行字节对齐的处理,并且在64位架构下,是以8字节进行内存对齐的。 二、内存对齐的原则 内存对齐应该是编译器的管辖范围,编译器为程序中的每个数据单元安排在适当的位置上,方便计算机快速高效的进行读取数据。 每个平台的编译器都有自己的对齐系数和相应的对齐规则。在iOS中的64位架构下,对齐系数就是8个字节。 三. 数据成员对齐 结构体或者共用体中的成员变量中,首个成员变量放在偏移量为0的位置上,后面的成员变量的对齐偏移量是取指定对齐系数和本身该成员变量所占用大小中的较小值,即min(对齐系数,成员变量的内存大小 ) 四. 数据整体对齐 在结构体或者共用体中的成员变量完成自身的对齐之后,整个结构体或者共用体也需要进行字节对齐处理,一般为min(对齐系数,最大成员变量的内存大小 )的整数倍。 结合上述原则1、2,可以推断出下面的常用原则,以结构体为例: 结构体变量的首地址是其最长基本类型成员的整数倍;