![](/img/trans.png)
[英]why do we increment/decrement stack pointer by “4” when we push and pop from the program stack?
[英]Why do subsequent Rust variables increment the stack pointer instead of decrementing it?
我覺得奇怪的是,當您在Rust中創建靜態分配的變量時,似乎隨着堆棧指針的增加而增加。 我知道不是這種情況,因為堆棧指針隨着分配的內存而減少。
如果要在C中做同樣的事情,我會發現隨着創建更多變量,堆棧指針會減少。
為什么這樣呢? Rust編譯器是否從下至上而不是從上至下分配這些?
fn main() {
let i1 = 1;
let i2 = 1;
let i3 = 1;
println!("i1 : {:?}", &i1 as *const i32);
println!("i2 : {:?}", &i2 as *const i32);
println!("i3 : {:?}", &i3 as *const i32);
}
當我運行該程序時,我收到以下消息:
i1 : 0x9f4f99fb24
i2 : 0x9f4f99fb28
i3 : 0x9f4f99fb2c
如果我使用C,我將得到:
i1 : 0x9f4f99fb2c
i2 : 0x9f4f99fb28
i3 : 0x9f4f99fb24
將堆棧視為功能堆棧幀序列,而不是可變地址序列。 不管堆棧增長的方向如何,它都會以整個堆棧幀的增量增長,每個堆棧幀的大小各不相同。
函數的堆棧框架的布局具有將變量綁定到的固定位置,類似於結構,但是不能保證框架內綁定的確切順序。 如果可以使該功能使用不同的布局更有效地利用空間,則可能會做到。 例如:
fn main() {
let i1: i32 = 1;
let i2: i64 = 2;
let i3: i32 = 3;
println!("i1 : {:?}", &i1 as *const i32);
println!("i2 : {:?}", &i2 as *const i64);
println!("i3 : {:?}", &i3 as *const i32);
}
// i1 : 0x7fff4b9271fc
// i2 : 0x7fff4b927200
// i3 : 0x7fff4b92720c
在此, i3
在 i2
之前存儲。 i64
需要與64位的倍數對齊,因此將兩個i32
存儲在一起而不是i32
是更緊湊的。 這不會發生在調試版本中,編譯器也可以選擇存儲i3
先用同樣的效果,所以我們不能和不應該依賴於這種排序。
也有可能出於任何其他優化原因(例如緩存訪問效率)對變量進行重新排序。
要查看堆棧確實向下增長,請考慮一個具有多個功能的示例:
fn main() {
let i1 = 1;
println!("i1 : {:?}", &i1 as *const i32);
another();
}
#[inline(never)]
fn another() {
let i2 = 2;
println!("i2 : {:?}", &i2 as *const i32);
}
// i1 : 0x7fffc7601fbc
// i2 : 0x7fffc7601f5c
another
由main
調用,因此其堆棧幀具有較低的地址。 注意,我不得不強制編譯器不要內聯函數,否則組合的布局將是任意的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.