Я пытаюсь получить более глубокое понимание того, как работают низкоуровневые операции языков программирования, и особенно то, как они взаимодействуют с ОС/ЦП. Я, наверное, прочитал каждый ответ в каждом потоке, связанном с стеком/кучей, на Stack Overflow, и все они блестящие. Но есть еще одна вещь, которую я еще не полностью понял.
Рассмотрим эту функцию в псевдокоде, который имеет тенденцию быть действительным кодом ржавчины; -)
fn foo() {
let a = 1;
let b = 2;
let c = 3;
let d = 4;
// line X
doSomething(a, b);
doAnotherThing(c, d);
}
Вот как я предполагаю, что стек выглядит как на линии X:
Stack
a +-------------+
| 1 |
b +-------------+
| 2 |
c +-------------+
| 3 |
d +-------------+
| 4 |
+-------------+
Теперь все, что я прочитал о том, как работает стек, заключается в том, что он строго подчиняется правилам LIFO (последний раз, первый раз). Точно так же, как тип данных стека в .NET, Java или любой другой язык программирования.
Но если это так, то что происходит после строки X? Потому что, очевидно, нам нужно работать с a
и b
, но это означало бы, что OS/CPU (?) Должен сначала выскочить d
и c
, чтобы вернуться к a
и b
. Но тогда он выстрелил бы себе в ногу, потому что ему нужно c
и d
в следующей строке.
Итак, мне интересно, что точно происходит за кулисами?
Другой связанный вопрос. Рассмотрим, что мы передаем ссылку на одну из других функций, подобных этой:
fn foo() {
let a = 1;
let b = 2;
let c = 3;
let d = 4;
// line X
doSomething(&a, &b);
doAnotherThing(c, d);
}
Из того, как я понимаю вещи, это будет означать, что параметры в doSomething
по существу указывают на тот же адрес памяти, что и a
и b
в foo
. Но опять же это означает, что нет стека, пока мы не дойдем до a
и b
.
Эти два случая заставляют меня думать, что я не полностью понял, как точно работает стек и как он строго следует правилам LIFO.