又是菜鸡的记录日志,局部变量大小,坑人的编译器

其实主要是想说明编译器太坑了(以下都是在32位环境下)
刚开始使用的是vs2010,一个int a ,缓冲区都要增大0xC

我人都傻了,两个int 增大0x18, char c[12] 增大0x20
一个double 直接占用0x10 ,值放在0x4-0xC 形成 4 8 4
疯狂的浪费空间,我也不晓得原因,先做个记录帖,以后再翻案吧
 

然后再装一个vc6,就完全符合我的预期
局部变量(定义局部变量在缓冲区中)
char a; 四个字节
short a;四个字节
int a; 四个字节
double a;八个字节
char a[3];char a[4] ;四个字节

总结1:局部变量会根据CPU宽度进行对齐
注意 连续两个char 也分别占四字节,总共占8字节,原因,局部变量使用频率较高,一般数量不多,使用空间换时间,CPU执行取存四个字节最快
例如:char还要有无符号扩展才能传,就麻烦,四字节就直接传,将局部变量设置为0x00 00 00 char 这样只要mov al,XXX或者mov byte ptr [],xxx 减少了一条命令

但是如果在结构体或者字符串中时,就会进行合并
#pragma pack(n)                       vc6默认pragma pack(8) (这里没看官方文档,听海哥讲的,不确定)

规则是 min(n,类型),并且最后长度为n的整数倍,n只能取2,4,8,16(不确定)写6警告但是对齐不以6
写的过大,编译器会将其变小到最大基础变量长度,(自己遍历一遍找个最大基础定义数据类型)
#pragma pack(8) 
struct {
int a;                                               //min(4,8)  4    4 a a a a                    
char b:                                            //min(1,8)  1    4 b ?               //这个?是short补的
short c;                                           //min(2,8)   2   4  c c ??       注意short要以2对齐,前面就5个所以补一个
double d:                                        //min(8,8)   8   4 1 ? 2 8                  结束
};
#pragma pack() 

a a a a b ? c c
d d d d d d d d

共计16字节
#pragma pack(1) 
struct {                                             min(类型,n)   小的数   实际占的空间
int a;                                               //min(4,1)  1    4                  
char b:                                            //min(1,1)  1    4 1 
short c;                                           //min(2,1)   1   4  1 2 
double d:                                        //min(8,1)   1   4 1  2 8                  结束
};
#pragma pack() 
4 1 2 8
共计15字节
waring :expected pragma parameter to be '1', '2', '4', '8', or '16' 编译器警告
继续提升难度

struct test
{
    char a[6];
};

struct test2
{
    char a;
    int b;
};

struct ttest
{
    char a;
    struct test tt;
    char b;
    int c;
};

struct ttest2
{
    char a;
    struct test2 tt;
    char b;
    int c;
};
根据内存 ttest
a          tt.a[0]          tt.a[1]       tt.a[2]
tt.a[3]   tt.a[4]          tt.a[5]        b
c           c                c               c 
12个字节
根据内存 ttest2
a           ?                ?               ?
tt.a        ?                 ?               ?
tt.b        tt.b             tt.b             tt.b
b           ?                  ?               ?
c            c                  c                c
20字节,好难啊
为啥ttest 合并了数组  ttest2没有合并呢
猜测 test 和 test2的字符宽度不一样
test的字符宽度为1
即 ttest
char a
char tt[6]
char b
int c
test2的字符宽度为4
即ttest2
char a
int tt[2]
char b
int c
解决,感觉没毛病

总结2:
结构体,如果不加
#pragma pack()  根据最长数据类型对齐(数组算单个元素长度,结构体里结构体也是这样计算)
如果加了就会根据两者小的那个进行数据类型对齐。

1.即遍历结构体 get 最长数据类型长度 
2.最长数据类型长度和 #pragma pack(n) 取小值
3.根据小值对齐
附:结构体里结构体就要看内部结构体的数据宽度而形成的类数组,
个人总结:不确定对错,目前没出问题

完事,因为编译器选择,基础规则也有所变化,留意这个坑点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值