RUST编译结果的疑惑?
非常简单的测试代码:
fn main(){ let _a = true; let _b = false; let _s:u32 = 17; let _c = true; let _d = false; //println!("{:p}", &s); //println!("{:p}", &c); //println!("{:p}", &d); }
(可以直接在play.rust-lang.org上查看编译结果,比较方便,免得记那么多rustc的编译指令了。)编译后:
playground::main: # @playground::main # %bb.0: subq $12, %rsp movb $1, 2(%rsp) movb $0, 3(%rsp) movl $17, 4(%rsp) movb $1, 10(%rsp) movb $0, 11(%rsp) addq $12, %rsp retq # -- End function
subq - 移动栈顶,为局部变量腾位置
mov* - 给栈帧赋值
这里可以看出,几个bool没什么大问题。(虽然也不知道第一个为什么要放到 2(%rsp)里,而不是直接放到栈顶呢??? )
在 let _s:i32之后的 let c = true;就显得很奇怪了。明明可以直接 moveb $1, 8(%rsp),为什么要多空出两个字节呢? 赋值给 10(%rsp)? 多出来的这两个字节有什么特别的用处吗?
当然,这些不影响整个临时栈的使用, 反正最后又add 12 rsp了,直接把栈顶还原了,即便是浪费,但不影响结果。
---------------------------
之所以好奇这个问题的原因,本来是在测试打印变量地址,好简单查看和计算变量实际占用空间大小的问题,结果发现减出来的结果不太对,就看了下汇编代码,才发现这个奇怪的现象的,如果用 u8 u16,好像依然是紧凑布局的,但是u64就空出来更多的字节了。
如果真想测试大小,在mem还有ptr的模块里,好像有几个专门的方法,如果就是想自己去计算查看,并且看具体地址,可以在struct里定义各种类型的变量,然后在去获取地址
当然,为了防止优化, 可以标记一下属性 repr(C) 或者 repr(packed),好取消RUST编译优化和设置内存布局的紧凑模式.
(如果同时需要,就写成 #[repr(C,packed)] 就行了)
~奋力追求梦想的泰坦~