teaLeef
teaLeef

Reputation: 1989

Using a structure definition in c

I defined structures in C like this:

struct cache_line{
    char valid;
    int tag;
    int LRU;
};


struct cache_set{
    struct cache_line *lines;
};


struct cache{
    struct cache_set *sets;
};

After these structures definitions, I define a function:

void do_something(struct cache_set *a_cache_set, int number){
            *a_cache_set.lines[next].tag = tag;
            *a_cache_set.lines[next].LRU = *current_count;
            *a_cache_set.lines[next].valid = 1;
}

In the main, I define a cache_set and do:

struct cache_set a_cache_set = my_cache.sets[setid];
int a_number  = 10;

do_something(&a_cache_set, a_number);

However, when compiling, I get the following error at the do_something definition (at

        *a_cache_set.lines[next].tag = tag;
        *a_cache_set.lines[next].LRU = *current_count;
        *a_cache_set.lines[next].valid = 1;

) :

error: request for member ‘lines’ in something not a structure or union

Yet, I explicitly declared a_cache_set as a cache set which contains lines...

What is wrong here?

Upvotes: 1

Views: 84

Answers (4)

zwol
zwol

Reputation: 140445

The operator precedence rules for C say that

*a_cache_set.lines[next].tag = tag;

is interpreted the same as

*(a_cache_set.lines[next].tag) = tag;

so, you are applying the . operator to a_cache_set, and not *a_cache_set as you probably expected. Same problem on the other two lines.

The preferred way to write this sort of thing in C is with the -> operator:

a_cache_set->lines[next].tag = tag;

In fact, it could be said that unary * being a lower-precedence prefix operator is why -> exists. (Contrast, say, UCSD Pascal, where you would write a_cache_set^.lines.)

Upvotes: 2

YePhIcK
YePhIcK

Reputation: 5856

Your code *a_cache_set.lines[next].tag = tag; means the following:

  1. get the lines member from a struct or union referred to by a variable named a_cache_set
  2. do an indexing operation on lines
  3. access the tag member
  4. dereference the result from the previous operation
  5. assign tag's value to that dereferenced result

As it stands the very first operation in that list fails in your code as the variable a_cache_set is a pointer which is not dereferenced yet.

The fix is (as suggested already in comments) to dereference using -> operator

Upvotes: 2

R Sahu
R Sahu

Reputation: 206567

This is an operator precedence issue.

    *a_cache_set.lines[next].tag = tag;
    *a_cache_set.lines[next].LRU = *current_count;
    *a_cache_set.lines[next].valid = 1;

is equivalent to

    *(a_cache_set.lines[next].tag) = tag;
    *(a_cache_set.lines[next].LRU) = *current_count;
    *(a_cache_set.lines[next].valid) = 1;

What you need is:

    (*a_cache_set).lines[next].tag = tag;
    (*a_cache_set).lines[next].LRU = *current_count;
    (*a_cache_set).lines[next].valid = 1;

or, better,

    a_cache_set->lines[next].tag = tag;
    a_cache_set->lines[next].LRU = *current_count;
    a_cache_set->lines[next].valid = 1;

Upvotes: 6

merlin2011
merlin2011

Reputation: 75545

You are trying to use . operator on a pointer. You have to use parenthesis to force dereference before ., or use -> operator instead.

(*a_cache_set).lines[next].tag = tag;
(*a_cache_set).lines[next].LRU = *current_count;
(*a_cache_set).lines[next].valid = 1;

Option B:

a_cache_set->lines[next].tag = tag;
a_cache_set->lines[next].LRU = *current_count;
a_cache_set->lines[next].valid = 1;

Upvotes: 4

Related Questions