【基础备忘】求sizeof struct

转自牛客网

一:

1.什么是内存对齐

假设我们同时声明两个变量:

char a;

short b;

用&(取地址符号)观察变量a,

b的地址的话,我们会发现(以16位CPU为例):

如果a的地址是0x0000,那么b的地址将会是0x0002或者是0x0004。

那么就出现这样一个问题:0x0001这个地址没有被使用,那它干什么去了? 答案就是它确实没被使用。 因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。

但是如果b的地址为0x0002,

那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。

2.结构体内存对齐规则(请记住三条内存规则(在没有#pragam pack宏的情况下)

结构体所占用的内存与其成员在结构体中的声明顺序有关,其成员的内存对齐规则如下:

(1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。

(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,结构体数组的时候,可以最小化长度。

(3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。

(4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。

3.实例演示:

struct A

{

char a;   //内存位置:  [0]

double b;   // 内存位置: [8]...[15]

int c;    // 内存位置: [16]...[19]  ----  规则1

};        // 内存大小:sizeof(A) = (1+7) + 8 + (4+4) = 24, 补齐[20]...[23]  ----  规则3

struct B

{

int a,    // 内存位置: [0]...[3]

A b,       // 内存位置: [8]...[31]  ----  规则2

char c,   // 内存位置: [32]

};         // 内存大小:sizeof(B) = (4+4) + 24 + (1+7) = 40, 补齐[33]...[39]

*注释:(1+7)表示该数据成员大小为1,补齐7位;(4+4)同理。

二:

第一个,8字节

第二个,2字节,加起来是10,是2的倍数,不用对齐

第三个,4字节,加起来是14,不是4的倍数,对齐到16

第四个,8字节,加起来是24,是8的倍数,不用对齐

所以一共是24字节

多看看就背住了:

32位编译器:32位系统下指针占用4字节

      char :1个字节

      char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

      short int : 2个字节

      int:  4个字节

      unsigned int : 4个字节

      float:  4个字节

      double:   8个字节

      long:   4个字节

      long long:  8个字节

      unsigned long:  4个字节

64位编译器:64位系统下指针占用8字节

      char :1个字节

      char*(即指针变量): 8个字节

      short int : 2个字节

        int:  4个字节

      unsigned int : 4个字节

      float:  4个字节

      double:   8个字节

      long:   8个字节

      long long:  8个字节

      unsigned long:  8个字节

时间: 2024-10-13 22:49:39

【基础备忘】求sizeof struct的相关文章

UITextView -- 基础备忘

UITextView 这篇文章只涉及到基本的使用,日后会写一些关于结合TextKit的备忘 基本属性 let screenSize = UIScreen.mainScreen().bounds.size let textView = UITextView(frame: CGRectMake(0, 20, screenSize.width, 200)) textView.font = UIFont.systemFontOfSize(20) textView.selectable = false t

【基础备忘】 二叉树前序、中序、后序遍历相互求法

转自:http://www.cnblogs.com/fzhe/archive/2013/01/07/2849040.html 今天来总结下二叉树前序.中序.后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出,下面我们分别说明. 首先,我们看看前序.中序.后序遍历的特性: 前序遍历:     1.访问根节点     2.前序遍历左子树     3.前序遍历右子树 中序遍历:     1.中序遍历左子树     2

ajax基础------备忘

1:register.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dt

基础备忘

1.虚函数不能被内联.   因为“内联”意味着“在编译时刻用被调用函数的函数体来代替被调用的函数”.但是“虚函数”意味着“运行时刻决定被调用的是哪一个函数”. 2.多重继承一般要求基类为虚基类.   不是虚基类的话,如果一个派生类有多于一条通向基类的继承路径,基类的数据成员会被复制到每一个继承类的对象里,继承类与基类间的每条路径都有一个拷贝.把基类定义为虚基类则可以消除这种重复.   class A {};   class B : virtual public A {};   class C :

scala基础备忘

声明一个变量 声明一个常量 显式指定类型 定义一个main函数 package org.admln.scala class HelloScala { } object HelloScala { def main (args: Array[String]) { println("hello scala") } } 定义一个普通函数 package org.admln.scala class HelloScala { } object HelloScala { def main (args

【基础备忘】基数排序

转自:http://www.cnblogs.com/kaituorensheng/archive/2013/02/23/2923877.html 基本思想 假设数序列中小于元素a的个数为n,则直接把a放到第n+1个位置上.当存在几个相同的元素时要做适当的调整,因为不能把所有的元素放到同一个位置上.计数排序假设输入的元素都是0到k之间的整数. 回到顶部 参考代码 #include <stdio.h> void COUNTINGSORT(int *A, int *B, int array_size

【基础备忘】JSON与XML的区别比较

转自:http://www.cnblogs.com/SanMaoSpace/p/3139186.html 1.定义介绍 (1).XML定义扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准.XML是标准通

R语言基础备忘 plot()详解

plot是R中的基本画图工具,直接plot(x),x为一个数据集,就能画出图,soeasy!但是细节往往制胜的关键.所以就详细来看下plot的所有可设置参数及参数设置方法. 下面讲到的图形参数,是graphic包中的常见参数,graphic不同图形方法中,这些参数都是相同的. type图形的类型 "p"点图 "l"线图 "b"点线图,线不穿过点 "c"虚线图 "o"点线图,线穿过点 "h"

linux网络基础(备忘)

1.如何让自己活得久一点,程序员 http://www.yeeyan.com/articles/view/31069/10175 在以太网的世界里,除了要网卡,还要有网线升级以及线路之间的交换器都要升级到相应的传输速率水平.ji 1.信号衰减的问题: 电子信号是存在衰减的,当长度达到100米时,就会很有可能出现问题.还有1.网线折的太严重,比如被门挤到,自行压制水晶头,缠绕度不够,风吹日晒的线路老化都会让信号衰减以及链接质量的问题:比如我之前遇到的一会链接上,一会连接不上,就是水晶头的制作有问题