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.
Related
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.
I am writing a generic linked list implementation in pure C.
struct Node {
void *value;
struct Node *next;
};
struct LinkedList {
struct Node *start;
struct Node *end;
};
void LinkedList_new(struct LinkedList* llist) {
llist->start = 0;
llist->end = 0;
return;
}
void addNode( struct LinkedList *ll, void *_value ) {
if ( NULL == ll->start ) {
ll->start = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->start;
} else {
ll->end->next = (struct Node *) malloc( sizeof(struct Node) );
ll->end = ll->end->next;
}
ll->end->value = _value;
return;
};
This all works great. My problem is when I get to printing value to the screen. I can't seem to find a generic implementation for printing.
Is there a way to determine the TYPE allocated to void *? (And then just do conversion using a switch statement)
void printFunc(int aInt) {
char str[15];
sprintf(str, "%d", aInt);
printf(str);
}
This is an implementation that works for int. Worst case I was thinking was writing a different function for each TYPE. Is this really my only route when using void *?
Is there a better way to do this?
No, there's no way to figure that out from the pointer alone. That would require type information to be stored at some well-defined location in all run-time structures, which is simply not how C uses the machine.
The common solution is for the user of the datatype to provide the print function that the application needs, since the application will know the type of data being stored. That is, there is usually an iteration function that takes a function pointer, calling the user's function (which might print the element) on each element of the list.
Here's how such a function could look:
void LinkedList_foreach(const LinkedList *start,
bool (*func)(void *element, void *data), void *data);
The above should call func() for each element of the list, passing it the element's data and the additional user-supplied data pointer which can be used by the caller to maintain state for the traversal. The callback func() should return false to stop the iteration, true to keep going.
To print an integer, assuming the integers are stored in the pointers, you could have:
static bool print_int(void *element, void *data)
{
printf("%d\n", (int) element);
return true;
}
Also, please don't cast the return value of malloc() in C.
Trying to implement below code for some assignment but getting an error for malloc array generation "[Error] conflicting types for 'stack'" Any Help ??
Thanks in Advance.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
int main()
{
printf("YO\n");
return 0;
}
EDIT :
I can't move it to main , as i have to access the stack globally in different functions.
because Stack array gets destroyed when it go to another function.
check here http://ideone.com/5wpZsp ,
When i give static declaration globally it works smoothly, here : http://ideone.com/3vx9fz
You can not call assignment operations at global scope. Try malloc operation in main() instead.
And the type of stack is not a pointer but pointer to pointer. Are you sure about it's declaration ?
Move your initialization of stack to inside of the main method.
EDIT An example showing how the malloc data can persist to other function calls even though malloc is called inside of main.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
void test_stack()
{
printf("%p\n", stack);
printf("%d\n", stack[19]->flag);
}
int main()
{
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
stack[19] = (NODEPTR*)malloc(sizeof(struct treenode));
stack[19]->flag = 42;
test_stack();
return 0;
}
Step 1: Move the declaration of stack inside main. There's no reason it should be declared globally:
int main( void )
{
NODEPTR *stack;
...
Step 2: Move the malloc call inside main (you cannot perform an assignment or a function call outside of a function).
Step 3: Drop the cast; it's unnecessary1 and just adds visual clutter.
Step 4: Use sizeof *stack as opposed to sizeof (NODEPTR) in the argument to malloc:
stack = malloc( sizeof *stack * 20 );
The result is the same, but this is easier to read, and avoids maintenance headaches if you ever change the type of stack.
Step 5: free your stack when you're done. Yeah, for this program it doesn't matter, but it's a good habit to get into.
So after all this, your code should read:
int main( void )
{
NODEPTR *stack;
stack = malloc( sizeof *stack * 20 );
...
free( stack );
return 0;
}
Stylistic nit: Hiding pointer types behind typedefs is bad juju IME. Pointer semantics are important, and if the programmer is ever expected to dereference an object of type NODEPTR (either explicitly, as (*node).info, or implicitly, as node->info), then it's usually best to declare that object using pointer declaration syntax, something like
typedef struct treenode Node;
Node *node;
Node **stack;
...
stack[i]->next = node->next;
etc. so the person using your types knows exactly how many levels of indirection are involved and can write their code accordingly (multiple indirection is not hard). If the type is meant to be truly opaque and never directly dereferenced, but just passed around to an API that handles all that, then hiding the pointerness of that type is okay. Otherwise, leave it exposed.
I tend not to typedef struct types for a similar reason, but I suspect I'm an outlier in that regard.
Ahd who broke the code formatter?!
1 - In C, that is; in C++, the cast is required, but if you're writing C++, you should be using new instead of malloc anyway.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
int main()
{
stack=malloc(sizeof(NODEPTR)*20);
printf("YO\n");
return 0;
}
This will work.
allocate memory inside(malloc) your main.
There is no need to typecast out put of malloc. for further info see this post
EDIT :
In your comment you mentioned that memory will be destroyed when you move other function.
This is not true. Once you allocate memory using malloc it will not be destroyed until you call free().
So if you want to access the malloc'ed variable in other function pass the variable as argument to other function.
See this example program below
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
char *str;
void passMalloc(char **str);
int main()
{
str = malloc(100 * sizeof(char));
strcpy(str, "GoodMorning");
printf("\nMain before pass : %s\n", str);
passMalloc(&str);
printf("Main after pass : %s\n\n", str);
free(str);
return 0;
}
void passMalloc(char **str)
{
strcpy(*str, "GoodEvening");
printf("Function Def : %s\n", *str);
}
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);
I am confused! Trying to create dynamic linked list and want to assign header by "malloc" function. From my code below compiler gives 2 error:
in main: [Error] node' undeclared (first use in this function) and
**In functionnewnode':** [Error] `node' undeclared (first use in this function)
#include <stdio.h>
#include <stdlib.h>
struct node{
int a,b,c,d;
struct node *next;
};
struct node * newnode(int, int, int, int);
int main(){
struct node *header;
header=(struct node *)malloc(sizeof(node));
int a,b,c,d;
a=11;
b=2;
c=4;
d=5;
header->next=newnode(a,b,c,d);
printf("\n\n");
system("PAUSE");
return 0;
}
struct node * newnode(int aa, int bb, int cc, int dd)
{
struct node *temp;
temp=(struct node*)malloc(sizeof(node));
temp->a =aa;
temp->b =bb;
temp->c =cc;
temp->d =dd;
temp->next=NULL;
return temp;
}
I appreciate any advice! thank you!
There is no type node. You have type struct node and that's the one you need to pass to the sizeof operator.
Firstly, as #icepack already noted, the type is named struct node, not node. So, sizeof(node) does not compile. You meticulously used struct node everywhere in your code except in those two spots with sizeof.
Secondly, consider using the
T *p = malloc(n * sizeof *p); /* to allocate an array of n elements */
idiom for memory allocation. E.g. in your case
temp = malloc(sizeof *temp);
I.e. don't cast the result of malloc and prefer using sizeof with expressions, not with type names. Type names belong in declarations. The rest of the code should be as type-independent as possible.
As mentioned by previous answers, you have to use struct node when referencing to your structure.
However if you just want to use the declarative name node you can do as following:
typedef struct _node{
int a,b,c,d;
struct _node *next;
} node;
Here you do not need to use struct before you reference a node
Edit: wrong syntax