Поддержка компилятора для массивов | формальные параметры - PullRequest
0 голосов
/ 27 апреля 2018

Меня попросили реализовать массивы в основном с нуля в компиляторе, который компилирует язык, подобный Си (на самом деле язык является строгим подмножеством языка Си). Но я думаю, что это не имеет значения для вопроса.

Я расширил сканер и парсер, и все отлично работает для глобальных и локальных массивов (даже для многомерных массивов). В основном я выделяю 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;

Если я использую глобальные или локальные массивы, у меня есть адрес для начала массива, а затем я увеличиваю этот адрес на некоторое смещение, чтобы получить доступ к определенному элементу (потому что это способ хранения данных). В стеке все наоборот, насколько я понимаю результаты.

Моя проблема в том, что стек растет сверху вниз, поэтому, если у меня есть указатель стека, переменная должна храниться над ним. Это означает, что я не могу просто изменить знак адреса памяти.

Так как мне получить элементы массива по правильному индексу (а не по некоторым отрицательным индексам)?

Надеюсь, вопрос в некоторой степени понятен.

1 Ответ

0 голосов
/ 27 апреля 2018

Но стек имеет LIFO-структуру, что означает, что переменные хранятся в последовательности, противоположной определенной.

Этого не происходит. Единственное, что касается LIFO в стеке вызовов, это порядок кадров стека, то, что происходит внутри кадра, полностью зависит от вас. На простом языке, имеющем только локальные переменные статического размера, память, необходимая для всех их вместе, может быть выделена путем вычитания некоторого постоянного числа из указателя стека. Это выделение отменяется, когда функция остается, что делает ее LIFO, но нет никакого порядка, налагаемого на переменные в блоке, и особенно на внутреннюю структуру этих переменных.

...