passing array of structure pointer to a function - c

I am writing a program in which I have to pass an array of structure pointers to a function in main body as follows
struct node *vertices[20];
create_vertices (&vertices,20);
implementation of function is some thing like this
void create_vertices (struct node *vertices[20],int index)
{
}
in this I have to pass an array of structure pointers with index 20,
the declaration I did outside mains is as follows I
void create_vertices(struct node **,int);
However each time compiling the code gives me problem in these three lines only as
bfs.c:26:6: error: conflicting types for ‘create_vertices’
bfs.c:8:6: note: previous declaration of ‘create_vertices’ was here
bfs.c: In function ‘create_vertices’:
bfs.c:36:15: error: incompatible types when assigning to type ‘struct node’ from type ‘struct node *’
I am unable to understand how should I be doing this.
What I want to be able to do is:
Declare an array of structure pointers in main (which I already did).
Pass the address of array to function (here is where I goofed up).
Declare the correct prototype of function outside mains.
The code has to be on C and I am testing it on Linux.
Can some one point me?

The type of &vertices in the call create_vertices(&vertices, 20) is not what you think.
It is a pointer to an array of pointers to structs:
struct node *(*)[20]
and not
struct node **
Drop the & in the call and you'd be back in business.
The compilation (using GCC 4.7.0 on Mac OS X 10.7.4):
$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -c x3.c
x3.c: In function ‘func1’:
x3.c:16:9: warning: passing argument 1 of ‘create_vertices’ from incompatible pointer type [enabled by default]
x3.c:7:10: note: expected ‘struct node **’ but argument is of type ‘struct node * (*)[20]’
$
The code:
struct node { void *data; void *next; };
void make_node(struct node *item);
void func1(void);
void create_vertices(struct node **array, int arrsize);
void create_vertices(struct node *vertices[20], int index)
{
for (int i = 0; i < index; i++)
make_node(vertices[i]);
}
void func1(void)
{
struct node *vertices[20];
create_vertices(&vertices, 20);
}
Drop the & and the code compiles cleanly.

As you wrote: struct node *vertices[20]; declares an array of pointers to node. Now if you want to create a function that changes its elements, you should declare a function that takes this kind of array as an argument:
void create_vertices(struct node *arr[20], int size)
or since the size can be ommited in this case, it's better to declare it as:
void create_vertices(struct node *arr[], int size)
Note, that this function can be called like this: create_vertices(vertices, 20); which makes first argument of this function (arr) to point to first element of this array. You are able to change this array within this function and changes will be visible outside.
Let's say you have function void foo(struct node *ptr) that changes node that ptr points to. When you declare struct node *ptr; and pass to this function: foo(ptr);, it can change this node object and changes are visible outside, but it can't change the passed pointer ptr itself. When you need to change pointer within the function so that changes are visible outside, that's the situation when you pass an address of pointer to function taking pointer to pointer.

In the prototype of create_vertices, the first argument is a pointer to a pointer to a structure. In the definition the first argument is array of 20 pointers to a structure.
Both the prototype and the definition has to be the same.

Related

differs in level of indirection from int 'int ()'

I'm building a linked list and I'm attempting to build a function to add a node, to test I pass through a name and size.
I think call it with my head but I get some strange error that I can't debug.
struct Test{
char name[_MAX_NAME];
int size;
struct Test *next;
};
typedef struct Test *node;
node AddNode(node head, char name, int size);
in my Main
node head = NULL; // is this problem?
head = AddNode(head,"Test Name",110);
Error C2040 'AddNode': 'node (node,char,int)' differs in levels of
indirection from 'int ()'
Consider the message “'node (node,char,int)' differs in levels of indirection from 'int ()'”. In this message, the int () is the type one gets non-C-standard compilers from the default declaration that is provided when you do not declare a function. That is, when you use AddNode before its declaration, it is automatically declared as int AddNode().
Then, later in your code when your declaration of AddNode appears, your declaration contrasts with the default declaration, and the compiler prints this message.
To fix this, put a declaration of AddNode before you use it. Such a declaration must appear in each source file where it is used. (Actually, the declaration must appear in the C translation unit, which means all the files that are included when you compile a source file. The translation unit includes header files that are included with #include. You must have a declaration of AddNode either in the source file itself or in a file it includes.)
Additionally, you declare AddNode as node AddNode(node head, char name, int size); but pass "Test Name" for the second parameter. As a function argument, "Test Name" acts as char *, not char, so you probably want to change the declaration to node AddNode(node head, char *name, int size);.

Incompatible type for argument for struct array

I have a structure defined as
struct Bod{
int x, y;
};
Then I have a function
void add(struct Bod* s) {
h[++nh] = s;
}
And in next function, I tried to pass array into the previous function, which gives me error Incompatible type for argument 1 of function add()
void bfs(struct Bod* body, int start_index){
struct Bod* v;
add(body[start_index]);
...
}
And in main, I have created this array of struct like this
struct Bod body[m*n];
What did I miss?
Since body[start_index] gives you one element of body at index start_index, you end up passing in that single element to add().
If you want to pass in the array itself, you just need to pass in body as-is:
add(body);
Or, to pass in the array starting at a given index:
add(&body[start_index]);

Using right pointer type, dont want to cast with void *

Question regarding using the correct pointer type in my below code. When I try to initialize struct member function without type casting to void *, I got “initialization from incompatible pointer type” warnings ?
problem solved by typecasting but I want to use right pointer type instead of casting to void*.
Code snippet:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef void (*set_id)(int id);
typedef void (*set_name)(char *name);
typedef struct prop {
set_id *cb_setting_id;
set_name *cb_setting_name;
}prop;
prop *setting_id(int id) {
printf("ID:%d\n", id);
}
prop *setting_name(char *in) {
char *name;
name = in;
printf("Name:%s\n", name);
}
//Here type casted to void *, if not I get wrong pointer initalization
//error
prop cb_prop = { .cb_setting_id=(void *)setting_id,
.cb_setting_name=(void *)setting_name };
int main() {
prop *cb_event;
cb_event = &cb_prop;
cb_event->cb_setting_id = (void*)setting_id(2);
cb_event->cb_setting_name = (void*)setting_name("/dev/ttyS1");
return 0;
}
Without type casting, Warning are:
struct_callback.c:25:33: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
prop cb_prop = { .cb_setting_id=setting_id,
^
struct_callback.c:25:33: note: (near initialization for ‘cb_prop.cb_setting_id’)
struct_callback.c:32:26: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
cb_event->cb_setting_id = setting_id(2);
Check the definition of e.g. the set_id type alias, it is a pointer to a function taking an int argument and not returning anything. Then compare it with the setting_id function, which is a function that takes an int arguments and returns a pointer to prop. Those two types are not compatible. It's made even worse because the setting_id function is declared to return a pointer to prop but doesn't actually return anything.
And not only that, but the members in the structure are pointers to e.g. set_id which means that cb_setting_id is a pointer to a pointer to a function.
Later on you do
cb_event->cb_setting_id = (void*)setting_id(2);
This is wrong because it calls the setting_id function, and tries to assign the returned value to cb_event->cb_setting_id. But the setting_id function doesn't return anything.
The solution to the first problem is to make sure that both the set_id type and the function setting_id are equal.
The solution to the second problem is to not declare the members are pointers (since they already are), or by changing set_id to not be a pointer.
The solution to the third problem is to remove those lines, since the the first two solutions should solve the initial initialization of the cb_prop structure.
The types you're assigning to are incompatible.
The function setting_id is of type prop *(*)(int), but the cb_setting_id field is of type void (*)(int). Simiarly for setting_name.
You need to change the typedef to match the function. Also, you have one extra level of indirection in your struct definition than you need.
typedef struct prop prop;
typedef prop *(*set_id)(int);
typedef prop *(*set_name)(char *);
struct prop {
set_id cb_setting_id;
set_name cb_setting_name;
};
First of all your function pointer typedef does not match the actual functions, because you use different return types. But here you hide the pointer syntax behind a typedef:
typedef void (*set_id)(int id);
typedef void (*set_name)(char *name);
Therefore, these become pointer-to-function-pointer:
set_id *cb_setting_id;
set_name *cb_setting_name;
That's not what you want. Simply change the typedefs to:
typedef prop* set_id (int id);
typedef prop* set_name (char *in);
Please note that you are not allowed to cast a function pointer to/from a void*. Void pointers assume object pointers, not function pointers. So casting a function pointer to void* results in an invalid pointer conversion.

How to properly allocate memory for structs, arrays of structs inside a struct, and passing that array as a parameter

I've been quite aways away from C and as I am diving back into it I have found myself hitting a roadblock. I have the following structure:
typedef struct{
char id;
struct S *children[SIZE];
}S;
In my code I initially declare an array of structs...
struct S arr[SIZE];
But when I get to this point of trying to allocate my first child for my first member of arr...
arr[0].children[0] = (S*)malloc(sizeof(S));
I get this warning: warning: incompatible implicit declaration of built-in function ‘malloc’ warning: assignment from incompatible pointer type [enabled by default]
On top of this I'm getting an error that doesn't sound very logical to me. I have the following function:
int foo(S *children[SIZE]);
but when I call this line....
foo(arr[0].children);
I get this note: note: expected ‘struct S **’ but argument is of type ‘struct S **’
which to me just sounds silly, it is expecting the argument it is getting and is upset about it.
Any help in explaining what I should be doing to properly allocate this memory and achieve the same idea would be very much appreciated.
There is no struct S, only S which is a typedef of anonymous structure.
Define struct S too:
typedef struct S {
char id;
struct S *children[SIZE];
}S;
Or:
typedef struct S S;
struct S {
char id;
S *children[SIZE];
};
And do avoid casting return of malloc in C:
arr[0].children[0] = malloc(sizeof(S));
For your first problem, you need to do:
#include <stdlib.h>
at the top of your program, in order to call malloc successfully.
The second problem (as also pointed out by others) is that struct S in your class definition refers to a different struct than S. In C, struct tags are in a different "namespace" than type names.

C, pointer to function in struct, warning "assignment from incompatible pointer type"

I have a struct defined as follow:
typedef struct {
char (*behave) (int*);
} BEHAVIOURSTRUCT;
this struct is defined in a .h file and it is included in the .c file
There i have a global variable (MAX_BEHAVIOURS is defined as 3):
BEHAVIOURSTRUCT bhvr[MAX_BEHAVIOURS];
and in the init i try to assign this, but here i get the warning: "assignment from incompatible pointer type"
void init() {
bhvr[0].behave = BHVR_line_follow; // here
...
}
the function i am trying to asign
void BHVR_line_follow(int *currstate){
....
}
by the sound of it my declaration in the struct and the pointer to the function are not from the same build, but in my opinion they are. But most likely i am mistaken.
Here is your function, and the function-type required, side-by-side:
void BHVR_line_follow(int *currstate)
char (*behave) (int*)
The function-type required takes an int* and returns a char.
Your function takes an int* and returns void (nothing).
To summarize, the return-type of BHVR_line_follow is wrong.

Resources