Структуры с 2d массивами в C - PullRequest
2 голосов
/ 27 февраля 2012

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

У меня есть две из следующих структур:

typedef struct line_elems line;
typedef struct cache_handler *cache;

struct line_elems { // we don't care about valid/block bits in our simulator
  int tag;
  int freq; // for LRU principle
};

struct cache_handler {
  int hit;
  int miss;
  int evict;
  line **lines; // 2d array for sets
};

В инициализирован кеш:

cache make_cache(int s, int E) {
  int i;
  cache new = malloc(sizeof(struct cache_handler));
  new->hit = 0;
  new->miss = 0;
  new->evict = 0;
  line **new_line = malloc((1 << s) * sizeof(*new_line));
  for(i = 0; i < (1 << s); i++)
    new_line[i] = malloc(E * sizeof(struct line_elems));

  new->lines = new_line;
  return new;
}

Теперь я хочу создать систему для поиска по единственной строке в массиве 2d:

int search_lines(line *lines, int E, int tag, int frequency) {
  int i;
  for(i = 0; i < E; i++) {
    //continue here
  }
}

Я немного запутался в том, что именно я должен вводить вмоя функция search_lines.Если я введу: search_lines(cache->lines[0], E=5, tag=5, frequency=5) Будет ли он делать то, что я ожидаю?То есть будет ли он искать через одну строку в моем 2d массиве?Я чувствую, что cache->lines[0] - это не то же самое, что (line*).В чем разница между cache->lines и cache->lines[0]?Меня это смущает, потому что оператор -> неявно выполняет один уровень разыменования?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 27 февраля 2012

"What is the difference between a cache->lines and a cache->lines[0]?"

cache->lines - это struct line_elems**, который является вашим 2D-массивом. На самом деле это указатель на первый элемент вашего 2D-массива. Оператор -> используется, потому что cache равен cache_handler* = вы обращаетесь к членам struct cache_handler с ним.

cache->lines[0] - это struct line_elems*, который является одномерным массивом с индексом 0 = это также указатель на первый элемент вашего двумерного массива.

Обратите внимание, что освобождение этой памяти должно иметь порядок, противоположный вашему выделению:

line **new_line = malloc((1 << s) * sizeof(*new_line));
for(i = 0; i < (1 << s); i++)
    new_line[i] = malloc(E * sizeof(struct line_elems));

сначала вы освобождаете new_line[i], а после этого вы освобождаете new_line:

for(i = 0; i < (1 << s); i++)
    free(new_line[i]);
free(new_line);
2 голосов
/ 27 февраля 2012

Оператор -> не разыменовывает lines, он разыменовывает cache.Это необходимо, поскольку cache также является указателем (созданным при вызове malloc.) Таким образом, перед обращением к любому из его полей необходимо разыменовать его.

cache->lines - это line **

cache->lines[0] является line *

1 голос
/ 27 февраля 2012

Да, ссылка на cache-> lines [0] действительно возвращает указатель на ваш выделенный массив 'lines', и, следовательно, да, ваш примерный вызов на самом деле является правильным способом сделать это.

Помните, что cache-> lines - это выделенный массив указателей (второй вызов malloc).Он просто выделяет достаточно места для 2^s * the_size_of_a_pointer

Остальные нижележащие значения malloc выделяют достаточно места для E * size_of_a_line.

Так что, когда вы разыменовываете указатель на кеш (используя ->)затем преобразуйте указатель в строку (используя [0]), затем вы получите указатель памяти на E строк.

Затем в своей функции вы можете использовать lines[0], чтобы перейти к первой строке,и lines[E-1] для перехода к последнему из всех массивов указателей строк, переданных (на основе оператора [] для указателя данных cache->lines).

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