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 = ¤t;
*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, ¤t);
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
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).
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
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, ¤t 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
Related
I do not understand what is wrong with the following piece of code. I am trying to create a linked list in C. I am creating a typedef struct which I call a person, then I declare a pointer that points to that structure and I am trying to allocate some memory for it to be able to store all its components. The compiler gives back an error saying that 'head' does not name a type.
typedef struct node {
int num;
struct node *next;
} person;
person *head = NULL;
head = (person*)malloc(sizeof(node));
Assuming the assignment to head is in a function, it is still incorrect as node is not a valid type or variable. It's either struct node but as you typedef'd that you should use person
head = malloc(sizeof(person));
But as the variable head is already of type person* you can also do
head = malloc(sizeof(*head));
which has the advantage you no longer need to know the exact type name (should you ever change it)
Also note that casting the result of malloc is not needed and unwanted.
You will have to check for the result being NULL though.
I am stuck, as I don't understand what is this code doing:
struct node
{
int info; /* This is the value or the data
in the node, as I understand */
struct node *next; /* This looks like a pointer. But
what is it doing in real life? */
} *last; /* What is this and why is it
outside the body? What is this
thing doing? */
I know that when a node is created, it has a value, and it is pointing to some other node
but I don't understand the syntax.
Is this a better way of writing the code above?
Is there a simpler way of writing the same struct for better understanding?
In my lectures they presume that the student has understanding of what they teach.
Well, we can explain this to you, but we can't understand it for you.
Code snippet you've provided is definition of variable last, being pointer to newly defined structure type node. It can be written other way as:
typedef struct _node_t {
int info;
node_t *next;
} node_t;
node_t *last;
This way we define typedef, which is, say, alias of type definition to some short name — in this particular case, it aliases structure of two fields as the name node_t. Wherever you define something as being of type node_t, you tell compiler that you mean 'this should be aforementioned structure of two fields', and node_t *last means 'variable last should be pointer to node_t type'.
So, back to syntax:
struct foo {
int a;
float b;
void *c;
} bar, *baz;
means 'Define structure type foo, and make it contain three fields — integer a, float-point b and untyped pointer c, then make variable bar to be of this structure type, and make variable baz to point to this structure type'.
Now to pointer. What you see is called 'recursive definition', e.g. type mentions itself in it's own definition. They are okay, if language supports them (C does), but one could avoid recursive definitions in linked list node structure by specifying next node pointer to be just untyped:
struct node_t {
int info;
void *next;
};
This way you no longer reference node_t type from node_t type, but that adds you some inconveniences when using this type (you have to explicitly cast next to node_t type, like ((*node_t)(last->next))->info instead of just last->next->info).
If you feel you need additional reference, consider taking a look at interactive online tutorials, like http://www.learn-c.org/ (I'm not affiliated).
that is the simplest way to write a linked list node , but why name it last ? name it node instead , this makes it more understandable , but here's how it works.
when a linked list is first created it contains only the root node (the first node in a linked list) , when you add a node , you fill the info field with the data that node will hold (note that info may be any kind of data , character , string , int ...) then set next to NULL , since that node is the last node in the list.
when you add another node , you change the value of next to point to the node you just added and you set the value of next to NULL in the node you just created because now that is the last node in the list .
you can repeat this to add as many nodes as your memory allow you to.
this link may help you to better understand structures
typedef struct marks {
int m;
struct marks *next;
} marks_t;
This way we define a structure so that a Linked List can be formed. Now we have defined the last variable next as a "structure pointer" which gives us the address of the next element in the list (i.e. as structure only)!
The last element does not point to any node (here marks structure) and hence the pointer variable has NULL value.
Now to define the first element:
marks_t *list;
if (list == NULL) {
list = (marks_t *) malloc(sizeof(marks_t));
}
list->m = 15;
list->next = NULL;
Now if we want to add an element next to this (i.e. second element):
marks_t *next1;
next1 = (marks_t *) malloc(sizeof(marks_t));
next1->m = 27;
next1->next = NULL;
list->next = next1; // Storing address of next1 structure in list
Why do we have to pass a pointer to a pointer to manipulate a linked list? Why can't we just pass the pointer? I just dont understand the internals of what is happening logically.
I see it as passing in the pointer to the list would suffice, but apparently not.
It depends on your linked list implementation, but for the sake of argument, if you have implemented, say, a push function, like this:
typedef struct linked_list linked_list;
struct linked_list
{
int value;
linked_list *next;
};
void push(linked_list **head, int value)
{
linked_list *temp = *head;
*head = malloc(sizeof(linked_list));
(*head)->value = value;
(*head)->next = temp;
}
then the pointer to a pointer is necessary because, otherwise, you would be modifying push's local head variable, and not the caller's.
In C if you want to pass a parameter which is possibly modified by the function you pass a pointer to the variable containing the modified value:
void swap(int *i, int *j) // modifies the two parameter.
Now if this parameter is itself a pointer, you have to pass a pointer to a pointer. Take for example the function insert which insert a cell in front of a list. If you represent the list as a pointer to its first element, then this pointer has to be modified. So you pass a pointer to it:
with
typedef struct cell *list
void insert(list *pl, struct cell *pc)
^^
Since list is a pointer itself it is a pointer to a pointer since list * is the same as struct cell **.
There's no one line answer to this
Have at look at page no.12 (push()) in this document: http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
Best explanation according to me.
I'm just learning C, and I have a question about pointer parameters. My code is the following:
int Length(node *head)
{
int length = 0;
while (head) {
length++;
head = head->next;
}
return length;
}
The code in the book I'm reading says to do this though:
int Length(struct node* head)
{
struct node* current = head;
int count = 0;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
Is there really a difference? The way I'm reading my code is that I get a pointer to a node struct as a parameter. The pointer itself however, is a local variable that I am free to mutate as long as I don't dereference it first. Therefore, I can change the value of the pointer to point to a different node (the next node as it may be).
Will this cause a memory leak or is there some other difference I'm not seeing?
This code is for a linked list implementation. The node struct is defined as:
// Define our linked list node type
typedef struct node {
int data;
struct node *next;
} node;
Yes, they are both doing the same. But in the second example, it is more clear what the author is trying to do because of the code. In your first example, you're using the pointer head to reference nodes other than the head. That can be confusing.
You could write your function like this and your intend would be clear:
int GetLength(node* current)
{
int length = 0;
while (current != NULL)
{
length += 1;
current = current->next;
}
return length;
}
Your solution and reasoning is correct. The node argument is a local variable: a copy of the pointer passed to your function, allocated on the stack. That's why you can modify it from within the function.
There is no difference between the two solutions, at least not in functionality, modern compilers are most likely to optimize away the extra variable in the book's solution. The only slight difference is in style, many tend to take arguments as unmodifiable values just in case to avoid mistakes.
Your understanding of the argument-passing mechanics is correct. Some people simply prefer not to modify argument values, the reasoning being that modifying an argument tends to be bug-prone. There's a strong expectation that at any point in the function, if you want to get the value the caller passed as head, you can just write head. If you modify the argument and then don't pay attention, or if you're maintaining the code 6 months later, you might write head expecting the original value and get some other thing. This is true regardless of the type of the argument.
I have a simple question in understanding the pointers and struct definitions in the linked list code.
1)
typedef struct node
{
struct node* next;
int val;
}node;
here if I use two "node" when i initialize node *head; which node I am referring to?
2) Here I use an int val in the struct. If I use a void* instead of int is there any thing thats going to change ?
3)Also if I pass to a function
reverse(node* head)
{
node* temp = head; or node* temp = *head;
//what is the difference between the two
}
I am sorry if these are silly question I am new to c language.
Thanks & Regards,
Brett
<1>
in C you need to specify struct node for structs
struct node
{
...
} node;
the last 'node' is variable of type struct node
e.g.
node.val = 1;
and not a type.
if you want to use 'node' as a type you need to write
typedef struct node { .. } node;
<2>
if you use void* you will need a mechanism to handle what the pointers point to e.g. if void* points to an integer you need keep the integer either on the stack or the heap.
node n;
int value = 1;
n.val = &value; // pointing to a single integer on stack
int values[]={1,2,3};
n.val = values; // pointing to an array of integers on stack
void* ptr = malloc(sizeof(int));
n.val = ptr; // pointing to a single (uninit) integer allocated on heap
int* ptrval = (int*)ptr; // setting an int ptr to the same memory loc.
*ptrval = value; // ptrval now points to same as n.val does
<3>
reverse(node* head)
head is a pointer to your list, *head is the content of what the pointer points to (first node below)
head->[node next]->[node next]->[node
next]
EDIT: rephrased and edited.
EDITx2: apparently the question got edited and a typedef was added so the question was altered.
*head is the dereference of the pointer : ie the actual place in memory that is pointed to by the pointer head...
Think of head as a coat hanger and *head as the coat itself, if that helps.
ie:
struct * coat c; //this is a coat hanger, not a coat
....
struct coat k = *c;//this is the coat itself, not a coat hanger
For #1:
In C, struct's have a separate name space. So if you wrote:
struct foo { ... };
You then have to use struct foo to reference the type. If you tried just foo after the above definition, the compiler would give an error as it doesn't know anything about that unqualified name.
A typedef gives a type an alternate name. A typedef name does not need to be qualified, so once you do:
typedef struct foo foo;
You can now use an unqualified foo to reference the type. Since it's just an alternate name, you can now use struct foo and foo interchangeably.
For #2.
It's possible that if you changed val to a void * it could change the size of the entire structure. Whether that makes a difference will depend on how you've written the rest of your code.