Invalid use of void expression - c

I am working on a generic linked list for a class and having problems.
I am getting invalid use of void expression error on this line.
freeNode(L->head, L->freeObject( L->head->obj));
Here is the prototype for freeNode.
void freeNode(NodePtr node, void (*freeObject)(const void *));
Here is the struct for L (generic linked list).
struct list {
int size;
NodePtr head;
NodePtr tail;
unsigned long int (*compareTo)(void *);
char * (*toString)(void *);
void (*freeObject)(void *);
};
I know the problem is in with passing what should be a function pointer rather than the output of the function, but I can't figure out what my mistake is.

This prototype:
void freeNode(NodePtr node, void (*freeObject)(const void *));
Indicates that the second argument is a pointer to a function that returns void. However, the call:
freeNode(L->head, L->freeObject(L->head->obj));
The second argument is actually the result of calling L->freeObject(L->head->obj) which, itself, is simply void, not a pointer to function type.
If you want to pass a free function to freeNode, then you'd want to pass the pointer to the node as a third argument to freeNode and just pass L->freeObject as the second argument. So for example, you'd need to call, freeNode(L->head, L->freeObject, L->head->obj). Inside freeNode you could then call the function (from the second argument) with the node (third argument). Although without knowing what you want to do inside of freeNode and all its use cases, it's unclear what the best approach really is here.

Related

What is the typical prototype for a deallocation function in C?

Looking at code on examples on StackOverflow I've noticed two distinct prototypes for object deallocation:
struct foo *foo_create(int);
void foo_free_v1(struct foo *);
void foo_free_v2(struct foo **);
void bar() {
struct *foo = foo_create(7);
// ...
// Version 1
foo_free_v1(foo);
// Version 2
foo_free_v2(&foo);
}
The standard library function free uses the first form.
Is the second form idiomatic in C? If yes, for what purpose?
The ones that take a pointer-to-pointer do so because they have the added convenience of automatically nulling out your variable for you.
They might look like:
void foo_free_v1(struct foo *f) {
if (f == NULL) return; // This has been freed before, don't do it again!
free(f->a);
free(f->b);
free(f->c);
free(f);
}
void foo_free_v2(struct foo **f) {
if (*f == NULL) return; // This has been freed before, don't do it again!
free((*f)->a);
free((*f)->b);
free((*f)->c);
free(*f);
*f = NULL; // Null out the variable so it can't be freed again.
}
This attempts to protect against double-free bugs. How good of an idea that, is debatable. See the comment thread below.
In the first function
void foo_free_v1(struct foo *);
the original pointer used as an argument expression is passed to the function by value. It means that the function deals with a copy of the value of the pointer passed to the function.
Changing the copy does not influence on the original pointer used as an argument expression.
Consider for example the function definition
void foo_free_v1(struct foo *p)
{
free( p );
p = NULL;
}
This statement within the function
p = NULL;
does not change the original pointer to NULL. It sets to NULL the function local variable p. As a result the pointer used as an argument expression after calling the function will have an invalid value. That is a value that does not point to an existing object.
In the second function declared like that
void foo_free_v2(struct foo **);
the original pointer used as an argument expression is accepted by reference through a pointer to it. So dereferencing the pointer you have a direct access to the original pointer used as an argument expression.
Consider a possible function definition
void foo_free_v2(struct foo **p)
{
free( *p );
*p = NULL;
}
In this case in the statement
*p = NULL;
it is the original pointer that is set to NULL. As a result the original pointer does not have an invalid value.
Consider for example a sungly-linked list like
struct SinglyLinkedList
{
int data;
SinglyLinkedList *next;
};
In main you can declare the list like
struct SinglyLinkedList *head = NULL;
Then you can add new nodes to the list. As the pointer head is initialized then the function that adds new nodes will work correctly.
After that you can destroy the list.
If you will call the first function declared like
void foo_free_v1(struct SinglyLinkedList *head );
then after calling the function the pointer head declared in main will have an invalid value. That is there will be an inconsistency. The list does not have already elements but its pointer to the head ode is not equal to NULL.
Is you call the function declared lik
void foo_free_v1(struct SinglyLinkedList **head );
then indeed the pointer to the head node in main will be equal to NULL that indeed means that the list is empty. And if you have a function that checks whether a list is empty you can pass the pointer to the function without producing undefined behavior.
What is the typical prototype for a deallocation function in C?
Pass the pointer. Nothing is returned or rarely used if non-void.
void foo_free_v1(foo_type *);
Is the second form (foo_free_v2(&foo);) idiomatic in C?
No.
Classic foo_free(foo_type *) samples:
foo *f = malloc(sizeof *f);
...
free(f);
FILE *istream = fopen(...);
int count = fscanf(istream, ...);
long offset = ftell(istream, ...);
fclose(istream);
When to use foo_free_v2(&foo);?
Use foo_free_v2(&foo) when foo is not a pointer type.
Example:
typedef struct {
int object1;
int *object2;
int *object3;
...
} foo_type;
foo_type foo = { 0 };
foo_get_resources(&foo, ...);
foo_do_this(&foo, ...);
foo_do_that(&foo, ...);
foo_free(&foo);

Function pointer as parameter in C

Hi I've been looking over stackoverflow and I'm really struggling with function pointers as parameters.
I have the structure:
struct Node {
struct Node *next;
short len;
char data[6];
};
and the functions:
void selectionsort(int (*compareData)(struct Node *, struct Node *), void (*swapData)(struct Node *, struct Node *), int n);
compare(struct Node *a, struct Node *b);
swap(struct Node *a, struct Node *b);
selection sort serves only to call compare and swap:
void selectionsort(int compare(struct Node *a, struct Node *b), void swap(struct Node *a, struct Node *b), int n){
int i;
for (i = 0; i < n; i++){
compare(a, b);
swap(a, b);
}
}
(the contents above may be incorrect, I have yet to get to fooling around with the actual selectionsort function really).
The problem arises when I call selectionsort in main. I was under the impression this would work:
int main(int argc, char **argv){
int n;
struct Node *list = NULL;
for (n = 1; n < argc; n++)
list = prepend(list, argv[n]); //separate function not given here.
int (*compareData)(struct Node *, struct Node *) = compare; //not sure I needed to redeclare this
void (*swapData)(struct Node *, struct Node *) = swap;
selectionsort(compareData(list, list->next), swapData(list, list->next), argc);
//other stuff
return 0;
}
Note: the function prepend contains the malloc for the struct, so that's been dealt with.
The problem I'm having is no matter how I play around with my function declarations etc, I always get the following error:
warning: passing argument 1 of 'selectionsort' makes pointer from integer without a cast [enabled by default]
note: expected 'int (*)(struct Node *, struct Node *)' but argument is of type 'int'.
Any help explaining why I'm getting this error message and how to fix it would be immensely appreciated.
I understand that the function is expecting a function pointer but I assumed my code above would allow for compareto be called. Any input would be greatly appreciated, also this is for an assignment (so please help me avoid cheating) and the parameters int(*compareData)(struct Node *, struct Node *) void (*swapData)(struct Node *, struct Node *) were given.
In
selectionsort(compareData(list, list->next), swapData(list, list->next), argc);
you are passing the result of calling the function compareData. This is wrong.
The same holds for swapData.
Just pass the function itself (resp. a pointer to it):
selectionsort(compareData, swapData, argc);
In your call to selectionsort you are actually calling those function pointers, causing you to pass the result of those calls to selectionsort. They are normal variables, and should be passed to selectionsort like any other variable argument.
However, you don't actually need the variables, you can just pass the functions directly:
selectionsort(&compare, &swap, argc);
Note that the address-of operator is not strictly needed, but I prefer to use them to explicitly tell the reader that we are passing pointers to those functions.

Manipulating linkedlists in C

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.

placement of unary operator when using pointers in C

I am trying to learn about pointers in C, and don't understand why the unary * operator was appended to the end of the word "node" in the following code snippet:
struct node* CopyList(struct node* head) {
/* code here */
}
From my understanding of pointers, one can create a pointer with a statement like
int *pointerName;
and assign a "pointee" to it with a statement like
pointerName = malloc(sizeof(int));
and then dereference the pointer with a statement like
*pointerName = 4;
which will store the integer value 4 in the 4 bytes of memory (pointee location) which is "pointed to" by the pointerName pointer.
WITH THAT BEING SAID, what does it mean when the * is appended to the end of a word, as it is with
struct node*
???
Thanks in advance!
http://cslibrary.stanford.edu/103/
The location of the * ignores the whitespace between the base type and the variable name. That is:
int* foo; // foo is pointer-to-int
int *bar; // bar is also pointer-to-int
In both cases, the type of the variable is "pointer-to-int"; "pointer-to-int" is a valid type.
Armed with that information, you can see that struct node* is a type, that type being "pointer-to-node-structure". Finally, therefore, the whole line
struct node* CopyList(struct node* head)
means "CopyList is a function taking a pointer-to-struct node (called head) and returning a pointer-to-struct node"
int *pointerName; is the same as int * pointerName; or int* pointerName;. The data type is int* in all those cases. So struct node* is just a pointer to struct node.
struct node* CopyList
To understand better you should read it from right to left. Which says CopyList is a function returning a pointer to node.
You can use '*' either with type or with function name/variable name.But it is suggested to use it with return type while declaring methods, like shown below
struct node* CopyList(struct node* head) {
/* code here */
}
when declaring pointers of a type use * with the variable name. like shown below,
int *ptr;
Declaring in that way increases readability.
For example consider this case,
int* a,b,c;
The above statement is appearing like declaring three pointer variables of base type integer, actually we know that it's equals to
int *a;
int b,c;
Keeping the * operator near the data type is causing the confusion here, So following the other way increases readability, but it is not wrong to use * in either way.
node* means that the following function/variable/structure has type 'pointer to type node'.

Casting from void* to struct

I am passing data of type struct Person to a linked list, so each node's data pointer points to a struct Person.
struct Person {
char name[16];
char text[24];
};
I am trying to traverse the list and print the name/text in each node by calling
traverse(&list, &print);
Prototype for traverse is:
void traverseList(struct List *list, void (*f)(void *));
List is defined as:
struct List {
struct Node *head;
};
My print function accepts a void * data :
print(void *data) { .... }
I know I have to cast the data to struct Person, correct?
struct Person *person = (struct Person *)data;
printf("%s", person->name);
I know this is not sufficient since I am getting an "initialization from incompatible pointer type" warning. How can I successfully cast a void* in this case? Thank you.
The problem's not with the cast, or even with the way you're passing the function around. The problem is that your declaration of print is missing a return type, in which case int is usually assumed. The compiler is complaining because you're passing an int (*)(void*) to a function that's expecting a void (*)(void*).
It's easy to fix: simply add void in front of your print function declaration. See:
https://gist.github.com/ods94065/5178095
My print function accepts a void * data
I would say, rewrite your print function by accepting struct Person * .
Your traverseList function accepts a function pointer (which takes a void pointer), but it doesn't accept an argument for that void data. It seems that this is what you're after:
void print (void* data)
{
printf("%s", ((struct Person*)data)->name);
}
void traverseList (struct List *list, void(*f)(void*), void* data)
{
f(data);
}
Then you can call traverseList:
traverseList (&list, &print, &person);

Resources