0

As part of a larger project, I am trying to write a C function that searches an implemented sorted linked list for a value in the struct olnode. I'm receiving a few errors, however. I'm new to C and I'm struggling with pointers and double pointers and when to use what, so I think that's part of the problem, but I'm not sure how to fix the problem. All necessary headers are included. This is on Minix 2.0.4 using cc as the compiler.

I can provide any additional necessary code; as I'm unfamiliar with C I'm not sure how much I need to show so I'm providing what I think is needed and nothing more to keep it short.

Global code (other than headers):

#define POOLSZ 53
struct olnode {
    int eventnr;
    int eventfq;
    struct olnode *next;
};
typedef struct olnode olnode;
olnode pool[POOLSZ];
olnode *avail;    /* points to first available node */

Function that is returning errors (searches for the passed int, after completion *current should be the olnode that holds the current value):

void
srchfreq(olnode *list, int xfrequency, olnode **current)
{
    olnode *previous, *newnext;

    while(current->eventfq > xfrequency) {
        *previous = &current;
        *newnext = current->next;
        *current = *newnext;
    }
}

Function call of srchfreq() (in a different function):

/* *list points to the first node in the list
   (*current).eventfq is the value being searched for
*/

srchfreq(*list, (*current).eventfq, &current);

Errors (line numbers are edited to be with respect to lines in srchfreq() as given above):

line 6: illegal use of selector eventfq
line 7: cannot convert pointer to struct
line 8: illegal use of selector next
line 8: cannot convert pointer to struct
line 9: cannot convert struct to pointer
vaindil
  • 7,536
  • 21
  • 68
  • 127

3 Answers3

1
void
srchfreq(olnode *list, int xfrequency, olnode **current)
{
    olnode *previous, *newnext;

    while((*current)->eventfq > xfrequency) {
        previous = *current;
        newnext = (*current)->next;
        *current = newnext;
    }
}

Second part depends on types of arguments. If list declared as olnode *list, there is no need to dereference it, since function expects a pointer. Second and third arguments are wrong (one of them - to determine which one we need to know how current is declared).

keltar
  • 17,711
  • 2
  • 37
  • 42
  • `list` is originally declared as `olnode *list;`, and `current` is declared as `olnode *current;`. – vaindil Jan 30 '15 at 18:39
  • 1
    Then last line should be `srchfreq(list, (*current)->eventfq, &current);`. This implies that `current` is correctly set to first element, of course. – keltar Jan 30 '15 at 18:46
  • After `*current` is declared, the next line is `*current = **list;`. `olnode **list` is what is passed to the function (call it `A()`) that calls `srchfreq()`, and `A()` is what declares `current`. I'm trying to understand the concept of pointers; I don't quite grasp how adding the `*`s to parameters changes how that parameter acts in the function. If `current` were passed to `srchfreq()` as `*current` instead of the existing `**current`, how would that change things? (Not necessarily code-wise, but conceptually.) – vaindil Jan 30 '15 at 19:04
  • 1
    Your search have to save its result somewhere. Search's result is a pointer. For some reason you've chosen to use output parameter instead of return value - that's weird, but completely ok. But in C, all parameters passed by value - which means your function can modify them, but calling side will never see changes. To actually change something, you passing pointer to where you want to save result. Type of result you want is `olnode*`, so pointer to `olnode*` will be `olnode**`. Generic advice here is "don't add extra pointer layers (and hence extra *) unless you need it". – keltar Jan 30 '15 at 19:18
  • Okay, that makes a lot of sense. I don't want to ask directly for code as I want to understand the concepts, but I can't figure this out--what would I need to set `*current` to inside `A()` then? I was thinking that it should be `**current = *list;` based on your comment, but I get errors with that. Since `**list` is declared as `olnode`, would it need to be `**current = ***list;`? (Logic: `current` needs to be `olnode**` type, so it's `**current`, and since `**list` is passed into the function then `***list` is needed to make it a correct pointer. I'm really unsure.) – vaindil Jan 30 '15 at 19:27
  • 1
    No, that's not it. You want pointer result in `current`, so its type should be `olnode*` (and hence `&current` you pass to function becomes `olnode**`), so function can change value of this pointer. But it also reads its value before changing it, so you need to set value correctly. Which is `current=list`, if both types are `olnode*`. Basically, type of `&current` is `olnode**`, but type of `*current` is `olnode` - `*` operator have different meaning for variable declaration and its usage. [cdecl](http://cdecl.org/) may help you understanding concepts. – keltar Jan 31 '15 at 06:22
1

current has type olnode**, or pointer to pointer to oldnode. To get a pointer to an olnode, dereference the pointer once:

*current;

To get the olnode itself, dereference the pointer you got from dereferencing the pointer to the pointer

**current;

So in your case, to grab the field eventfq

(**current).eventfq

C also provides a shortcut where the operation (*ptr).field, is exactly equivalent to prt->field.

In your case, you could apply this with

(*current)->eventfq
Chris Rice
  • 1,390
  • 11
  • 16
1

Errors, in order of appearance:

  • Since current is a pointer to a pointer to a olnode, it can't refer to any fields directly; but *current can.
  • *previous is an olnode, &current is a pointer to a pointer to a pointer to a olnode.
  • See the first error
  • *newnext is a olnode
  • *current is a pointer to a olnode
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • I'm coming from Python and Java; I'm trying to wrap my mind around the concept of pointers. `current` is passed into the function as `**current`. Therefore, if I understand correctly, it's the fact that it has two `*`s that makes it a pointer to a pointer. Why then does adding a third `*` make it reference the `olnode` directly? I would think that would make it a pointer to a pointer to a pointer, though you said that's what `&current` is. (I'm trying to figure this out, I apologize if this comes across as telling you you're wrong. I genuinely have no idea so I'm not trying to be that way.) – vaindil Jan 30 '15 at 18:58
  • `*` is the dereference operator: follow a pointer. (And, as you seem to realize, `&` is the opposite operator, such that `*&x` is the same as `x`.) So the declaration `clnode **current` should be read as "a `clnode` is what you get after dereferencing `current` twice". – Scott Hunter Jan 30 '15 at 20:33