Где хранятся массивы в памяти? - PullRequest
3 голосов
/ 19 июня 2019

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

Но я не знаю, как сохраняется массивв памяти.Я попытался объявить глобальный массив:

  int tab[5]={10,9,12,34,30};

и в конце я прочитал содержимое памяти, я имею в виду, что после выполнения кода я прочитал содержимое памяти (например,Я работаю над микроконтроллером и знаю, куда сохраняются данные), когда я объявляю глобальную переменную, например, a = 10;и когда я читаю содержимое памяти, я нахожу значение 10 в памяти, но я не нахожу содержимое таблицы, которая составляет 10,9,12,34,30

Я хочу понять, гдесодержимое массива это сохранить в памяти?

Я работаю на Aurix Infineon, и я использую Hightec в качестве компилятора, я выполняю свой код прямо на aurix, я читаю запоминание так:

const volatile unsigned char * mem_start = 0xd0000000;
#define size ((ptrdiff_t) 0xfff)
unsigned char bufferf [size];
code ();
main(){
    ... 
    for (int e = 0; e < sizeof (bufferf); e ++) 
        bufferf [e] = * (mem_start + e); // read memory
}

Ответы [ 3 ]

1 голос
/ 20 июня 2019

Ответ на вопрос, где хранятся массивы или даже любые переменные, зависит от того, рассматриваете ли вы абстрактную машину или реальное оборудование. Стандарт C определяет, как все работает на абстрактной машине, но соответствующий компилятор может делать что-то еще на реальном оборудовании (например, из-за оптимизации), если наблюдаемые эффекты одинаковы.

(На абстрактной машине массивы обычно хранятся в том же месте, что и другие переменные, объявленные в той же области видимости.)

Например, переменная может быть помещена в регистр вместо стека или полностью оптимизирована. Как программисту вы, как правило, не должны заботиться об этом, поскольку вы также можете просто рассмотреть абстрактную машину. (Возможно, в некоторых случаях вы заботитесь об этом, и на микроконтроллерах с очень ограниченным объемом ОЗУ одна из причин может заключаться в том, что вы должны быть очень экономными в использовании стека и т. Д.)

Что касается вашего кода для чтения из памяти: он не может работать. Если size - это размер памяти, доступной для переменных, вы не можете поместить массив bufferf[size] в эту память вместе со всем остальным .

К счастью, копирование содержимого памяти в отдельный буфер не требуется. Рассмотрим вашу строку bufferf[e] = *(mem_start + e) - поскольку вы уже можете прочитать произвольный индекс e из памяти на mem_start, вы можете использовать *(mem_start + e) (или, лучше, mem_start[e], что в точности эквивалентно) непосредственно везде, где бы вы ни использовали bufferf[e]! Просто обработайте mem_start как указание на первый элемент массива size байтов.

Также обратите внимание, что если вы программно ищете содержимое массива tab, его элементы равны int с, поэтому они имеют более одного байта каждый - вы просто не найдете пять смежных байтов с этими значениями .

(Опять же, вы также можете просто взять адрес tab[0] и выяснить, где он хранится, т. Е. ((unsigned char *) tab) - mem_start - это индекс tab в mem_start. Однако, наблюдение за ним может измениться вещи из-за вышеупомянутой оптимизации.)

1 голос
/ 19 июня 2019
global variable is stored in memory, and the local variable is saved in the stack

Это неверно.

Глобальные переменные иногда хранятся в регистрах, а не только в статической памяти.

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

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

Существует множество математических моделей вычислений, и не все используют стек. Код можно преобразовать из одной модели в другую , сохранив тот же результат после оценки.

Вы получили эту информацию из книг, написанных в 70-х, 80-х годах, и в то же время процесс оценки кода значительно улучшился (с использованием методов, которые были теоретическими в 30-х годах, но в настоящее время применяются в системах).

0 голосов
/ 19 июня 2019

Эта программа может приблизить вас к тому, что вы хотите:

int tab[] = {10, 9, 12, 34, 30};

// Used to get the number of elements in an array
#define ARRAY_SIZE(array) \
    (sizeof(array) / sizeof(array[0]))

// Used to suppress compiler warnings about unused variables
#define UNUSED(x) \
    (void)(x)

int main(void) {
    int *tab_ptr;
    int tab_copy[ARRAY_SIZE(tab)];
    tab_ptr = tab;
    UNUSED(tab_ptr);
    for (int index = 0; index < ARRAY_SIZE(tab_copy); index++) {
        tab_copy[index] = tab[index];
    }
    return 0;
}

У меня нет среды Hightec для тестирования, и у меня нет Aurix для его запуска. Тем не менее, это может дать вам отправную точку, которая поможет вам получить информацию, которую вы хотите.

Похоже, что Infineon Aurix - это 32-разрядная машина с прямым порядком байтов. Это означает, что int будет иметь ширину 32 бита, а первый байт будет хранить первые 8 битов значения. Например, значение 10 будет храниться так:

0a 00 00 00

Если вы попытаетесь прочитать эту память как char, вы получите 0x0a, 0x00, 0x00 и 0x00.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...