昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵。一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧:

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

(ANSI C标准下,_INTSAIZEOF宏定义在stdarg.h中,Q3中定义在bg_lib.h中;bg_lib.h -- standard C library replacement routines used by code)

关于这个宏的内部原理,我们后面再谈,还是先理理“内存对齐”这词的意思吧,多年来一直模糊的存在于我的大脑中,究竟为什么要内存对齐啊。

内存对齐的根源

1、许多计算机系统对基本数据类型可允许地址作了一定的限制,要求某种类型对象的地址必须是某个值n(通常是2、4、8)的倍数,从而来简化处理器和存储器之间的接口的硬件设计。如Linux的对齐策略是2字节数据类型,例如short的地址必须是2的倍数。而较大的数据类型如:int、int*、float、double则必须是4的倍数。而Microsoft Windows的策略要求更为严格-----任何k字节对象的地址必须是k的倍数。比如要求一个double类型对象的地址必须是8的倍数(引自《深入理解计算机系统》)。

2、数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

内存对齐的规则

上面所提到的自然边界是由什么决定的呢,我想应该是由硬件平台决定的,至于操作系统和编译器(默认对齐系数)则都是依赖于上一层的。当然,编译器的对齐系数可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变;

举个例子:比如参数入栈,编译器并不是一个紧挨着一个的压入栈的,而是根据对齐系数来压栈的,比如一个char类型的参数,虽然本身只占一个字节,但是编译器会自动补全后面3个字节,然后再压下一个参数。

(这里说点题外话:在写过delphi程序的人都知道,有个packed的保留字,作用就是压缩数据结构,不要按对齐存储,除非数据结构体积庞大,否则为什么要用packed呢,用了不就影响内存读取的速度了吗?:))

1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。 
3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

(以上3点引自《也谈内存对齐》一文)

再看_INTSAIZEOF宏

这个宏的定义咋一看有点丈二和尚摸不着头脑,不过网上有对齐的解释,看后相信会豁然明朗了:

对于两个正整数 x, n 总存在整数 q, r 使得 
x = nq + r, 其中  0<= r <n                  //最小非负剩余 
q, r 是唯一确定的。q = [x/n], r = x - n[x/n]. 这个是带余除法的一个简单形式。在 c 语言中, q, r 容易计算出来: q = x/n, r = x % n. 
所谓把 x 按 n 对齐指的是:若 r=0, 取 qn, 若 r>0, 取 (q+1)n. 这也相当于把 x 表示为: 
x = nq + r', 其中 -n < r' <=0                //最大非正剩余 
nq 是我们所求。关键是如何用 c 语言计算它。由于我们能处理标准的带余除法,所以可以把这个式子转换成一个标准的带余除法,然后加以处理: 
x+n = qn + (n+r'),其中 0<n+r'<=n            //最大正剩余 
x+n-1 = qn + (n+r'-1), 其中 0<= n+r'-1 <n    //最小非负剩余 
所以 qn = [(x+n-1)/n]n. 用 c 语言计算就是: 
((x+n-1)/n)*n 
若 n 是 2 的方幂, 比如 2^m,则除为右移 m 位,乘为左移 m 位。所以把 x+n-1 的最低 m 个二进制位清 0就可以了。得到: 
(x+n-1) & (~(n-1))

C语言再学习之内存对齐的更多相关文章

  1. C语言再学习part1-宏观认识C语言

    天下莫柔弱于水,而攻坚强者莫之能胜,以其无以易之也.弱之胜强,柔之胜刚,天下莫不知行,莫能行. —老子 我近来每天都在坚持读书,所以我一直沉浸于古人的智慧中无法自拔.所以如果我这篇博文被你有幸看到,那 ...

  2. C语言深入学习系列 - 字节对齐&内存管理

    用C语言写程序时需要知道是大端模式还是小端模式. 所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中:所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高 ...

  3. C语言 结构体的内存对齐问题与位域

    http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...

  4. C语言结构体的内存对齐问题

    在C语言开发当中会遇到这样的情况: #include <stdio.h> struct test { int a; char b; }; int main(int argc, const ...

  5. 3.c语言结构体成员内存对齐详解

    一.关键一点 最关键的一点:结构体在内存中是一个矩形,而不是一个不规则形状 二.编程实战 #include <stdlib.h> #include <stdio.h> stru ...

  6. c语言基础学习08_内存管理

    =============================================================================涉及到的知识点有:一.内存管理.作用域.自动变 ...

  7. C语言再学习part3—算法

    君子远庖厨,万物皆备于我.—孟子 这篇文章主要总结程序的主要要素,以及程序的构成是什么样子的.最后说说我学到的一种奇特的表示算法的方式—伪代码. 让我们开始吧! 一个程序应该包括以下两个主要要素: 1 ...

  8. 01_c语言再学习_基础部分(1)

    目录: 1.编译基础 2.c语言关键字 3.c语言数据类型 4.二进制/8进制/16进制 5.计算机内存数值存储方式:sizeof/原码/反码/补码 6.c语言中的字符和字符串 7.c语言中的数组和字 ...

  9. C语言再学习之 setjmp与longjmp

    前不久在阅读Quake3源代码的时候,看到一个陌生的函数:setjmp,一番google和查询后,觉得有必要针对setjmp和longjmp这对函数写一篇blog,总结一下. setjmp和longj ...

随机推荐

  1. 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件

    转自:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...

  2. Linux下修改mysql密码

    # /etc/init.d/mysql stop# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &# mysq ...

  3. redis连接超时报错

    应用程序连接redis超时,报错如下: ERROR DubboServerHandler-xxx.xx.xx.52:20880-thread-172 2016-12-21 15:25:20,429 c ...

  4. R语言基础绘图

    一.可以通过代码或者图形用户界面保存图形,绘图语句夹在开启目标图形设备语句和关闭图形设备的语句之间: pdf("filename.pdf") png("filename. ...

  5. JS自执行匿名函数

    常见格式:(function() { /* code */ })(); 解释:包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命名函数,括号内为匿 ...

  6. CrossApp入门简介

    来自9miao社区的CrossApp号称可以极大的简化移动应用的开发,因为开源的时间不长,有效的资料不多. 官方网站: http://crossapp.9miao.com/ 环境搭建说明:http:/ ...

  7. Mini projects #3 ---- Stopwatch: The Game

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  8. 如果你觉得我的博客对你有帮助,请帮忙加点我所在团队博客访问量http://home.cnblogs.com/u/newbe/

    RT http://home.cnblogs.com/u/newbe/ 跪谢~

  9. git 证书错误

    git clone https://github.com/openstack-dev/devstack.git Cloning into 'devstack'... error: server cer ...

  10. String 归档

    1.古罗马皇帝凯撒在打仗时曾经使用过以下方法加密军事情报:,请编写一个程序,使用上述算法加密或解密用户输入的英文字串要求设计思想.程序流程图.源代码.结果截图. 设计思想: 1)输入一个字符串str( ...