Меня попросили реализовать массивы в основном с нуля в компиляторе, который компилирует язык, подобный Си (на самом деле язык является строгим подмножеством языка Си). Но я думаю, что это не имеет значения для вопроса.
Я расширил сканер и парсер, и все отлично работает для глобальных и локальных массивов (даже для многомерных массивов). В основном я выделяю 8 байт для каждой записи массива, например, arr [10] будет выделять 80 байт. Для адресации и присвоения значений я использую алгоритм основных строк.
Как упоминалось ранее, локальные и глобальные массивы работают нормально. Однако я не получаю массивы как формальные параметры для работы.
Так например
int test (int a[10]);
int main() {
int array[10];
int i;
i = 0;
while(i < 10) {
array[i] = i;
i = i + 1;
}
return test(array);
}
int test (uint64_t a[10]) {
return a[7];
}
Проблема здесь в том, что объявление метода (первая строка) резервирует память для формального параметра (который работает в моей реализации) в стеке. Но стек имеет LIFO-структуру, что означает, что переменные хранятся в последовательности, противоположной определенной.
Так что мой
return a[7];
должен вернуть значение 7. Но поскольку в стеке порядок элементов другой, мои значения сохраняются таким образом
a[-9] == 0;
a[-8] == 1;
a[-7] == 2;
a[-6] == 3;
.
.
.
a[-1] == 8;
a[0] == 9;
Если я использую глобальные или локальные массивы, у меня есть адрес для начала массива, а затем я увеличиваю этот адрес на некоторое смещение, чтобы получить доступ к определенному элементу (потому что это способ хранения данных). В стеке все наоборот, насколько я понимаю результаты.
Моя проблема в том, что стек растет сверху вниз, поэтому, если у меня есть указатель стека, переменная должна храниться над ним. Это означает, что я не могу просто изменить знак адреса памяти.
Так как мне получить элементы массива по правильному индексу (а не по некоторым отрицательным индексам)?
Надеюсь, вопрос в некоторой степени понятен.