de1337ed
de1337ed

Reputation: 3315

Structs with 2d arrays in C

I'm not very good at C yet so I have some questions.

I have two of the following structs:

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
};

In initialized the cache by:

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;
}

Now, I want to create a system to search through a single row in the 2d array:

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

I'm a little confused on what exactly I'm supposed to input into my search_lines function. If I input: search_lines(cache->lines[0], E=5, tag=5, frequency=5) Will it do what I'm expecting? That is, will it search through a single line in my 2d array? I feel that cache->lines[0] is not the same as a (line*). What is the difference between a cache->lines and a cache->lines[0]? This is confusing me because does the -> operator implicitly perform one level of dereferencing?

Thank you.

Upvotes: 2

Views: 1321

Answers (3)

LihO
LihO

Reputation: 42083

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

cache->lines is struct line_elems** which is your 2D array. Actually it is a pointer to first element of your 2D array. Operator -> is used because cache is cache_handler* = you are accessing members of struct cache_handler with it.

cache->lines[0] is struct line_elems* which is 1D array at index 0 = it is also a pointer to first element of your 2D array.

Note that freeing of this memory should have opposite order than your allocation:

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));

you free each new_line[i] first and after that you free new_line itself:

for(i = 0; i < (1 << s); i++)
    free(new_line[i]);
free(new_line);

Upvotes: 2

Wes Hardaker
Wes Hardaker

Reputation: 22252

Yes, the reference of cache->lines[0] does indeed return a pointer to your allocated array of 'lines', and thus yes your example call is in fact the right way to do it.

Remember that the cache->lines is a allocated array of pointers (the second call to malloc). It merely allocates enough space for 2^s * the_size_of_a_pointer

The rest of the mallocs below that allocate enough space for E * size_of_a_line.

So when you dereference the cache pointer (using ->) and then deference the lines pointer (by using [0]) then you end up with a memory pointer to E lines.

Then in your function, you can use lines[0] to get to the first line, and lines[E-1] to get to the last of whatever array of line pointers was passed in (based on the [] operator to the cache->lines data pointer).

Upvotes: 1

Tom
Tom

Reputation: 19304

The -> operator is not dereferencing lines, it is dereferencing cache. This is necessary because cache is also a pointer (created by a call to malloc.) Thus, it must be dereferenced before accessing any of its fields.

cache->lines is a line **

cache->lines[0] is a line *

Upvotes: 2

Related Questions