1. C语言结构体数据对齐
转自:http://blog.csdn.net/tiany524/article/details/6295551
1.1 结构体数据对齐(没有#pragma pack()宏定义)
结构体对齐可以总结为三个基本原则
①数据成员对齐规则:
结构体的数据成员中,第一个成员从offset为0的地址开始,以后每一个成员存储的起始位置为该成员大小的整数倍(在win32中int为32bit也即4字节对齐)
②结构体作为成员:
如果一个结构体1作为另一个结构体2的数据成员,则在结构体2中结构体1要从1内部成员最大的整数倍地址开始存储。
③结构体的总大小(sizeof):
为该结构体内部最大基本类型的整数倍,不足的要补齐,而不是简单的所有成员的大小总和。
举例说明
1 struct A 2 { 3 short a; 4 short b; 5 short c; 6 };
sizeof(A)=6
1 struct B 2 { 3 long a; 4 short c; 5 };
sizeof(B)=8
它的内存分配为: a1 a2 a3 a4 , c1 c2 x x(a1为a的第一个字节,x为补齐字节,下同)
1 struct C 2 { 3 int a; 4 char b; 5 short c; 6 };
sizeof(C)=8
它的内存分配为: a1 a2 a3 a4, b1 x c1 c2(原则1)
1 struct D 2 { 3 char a; 4 int b; 5 short c; 6 };
sizeof(D)=12
内存分配为: a1 x x x, b1 b2 b3 b4, c1 c2 x x
1 struct E 2 { 3 int a; 4 double b; 5 short c; 6 };
sizeof(E)=24
内存分布a1 a2 a3 a4 x x x x, b1 b2 b3 b4 b5 b6 b7 b7, c1 c2 x x x x x x
1 struct F 2 { 3 char a,b; 4 int c; 5 double d; 6 short e; 7 E h; 8 };
sizeof(F)=48
内存分布
a1 b1 x x, c1 c2 c3 c4 , d1 d2 d3 d4 d5 d6 d7 d8, e1 e2 x x x x x x, A的分布
1.2 加入#pragma pack()宏定义)
1 #pragma pack(1) 2 struct E 3 { 4 int a; 5 double b; 6 short c; 7 };
sizeof(E)=14,为实际内存
VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也可以屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
VC 中提供了 #pragma pack(n) 来设定变量以n字节对齐方式(n一般取1、2、4、8、16)。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必须为n的倍数。下面举例说明其用法。
1 #pragma pack(push) //保存对齐状态 2 #pragma pack(4)//设定为4字节对齐 3 struct test 4 { 5 char m1; 6 double m4; 7 int m3; 8 }; 9 #pragma pack(pop)//恢复对齐状态
以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为 m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。
2. 约瑟夫环问题
http://baike.baidu.com/view/717633.htm
问题描述:n个人(编号0~(n-1)),从0开始报数,报到m-1的退出,剩下的人继续从0开始报数。求胜利者的编号。
我们知道第一个人(编号一定是(m-1)%n) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始):
k k+1 k+2 ... n-2,n-1,0,1,2,... k-2
并且从k开始报0。
现在我们把他们的编号做一下转换:
k --> 0
k+1 --> 1
k+2 --> 2
...
...
k-3 --> n-3
k-2 --> n-2
变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!
∵ k=m%n;
∴ x' = x+k = x+ m%n ; 而 x+ m%n 可能大于n
∴ x'= (x+m%n)%n = (x+m)%n
得到 x‘=(x+m)%n
令f表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n].
递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)
3. 求出小于n的最大素数,并做时间复杂度优化
4. 不限长的数据运算问题,字符数组模拟大数