Function pointer confusion - c

I'm trying to use function pointers and Abstract data types in c. This is my first time using it and I'm really confused. Anyways when I tried to compile this code I gave me an error. The first time I ran it worked. But when I change the arguments by switch a and b. It gave me the old answer and never updated.
typedef struct data_{
void *data;
struct data_ *next;
}data;
typedef struct buckets_{
void *key;
}buckets;
typedef struct hash_table_ {
/* structure definition goes here */
int (*hash_func)(char *);
int (*comp_func)(void*, void*);
buckets **buckets_array;
} hash_table, *Phash_table;
main(){
Phash_table table_p;
char word[20]= "Hellooooo";
int a;
a = 5;
int b;
b = 10;
/*Line 11*/
table_p = new_hash(15, *print_test(word), *comp_func(&a, &b));
}
int *print_test(char *word){
printf("%s", word);
}
int *comp_func(int *i,int *j){
if(*i < *j){
printf("yeeeeeeee");
}else{
printf("yeaaaaaaaaaaaaa");
}
}
Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *, void *)){
int i;
Phash_table table_p;
buckets *buckets_p;
hash_table hash_table;
table_p = (void *)malloc(sizeof(hash_table));
/*Setting function pointers*/
table_p -> hash_func = hash_func;
table_p -> comp_func = cmp_func;
/*Create buckets array and set to null*/
table_p -> buckets_array = (buckets **)malloc(sizeof(buckets_p)*(size+1));
for(i = 0; i < size; i++){
table_p -> buckets_array[i] = NULL;
}
return table_p;
}
This is the error message:
functions.c: In function 'main':
functions.c:11:26: error: invalid type argument of unary '*' (have 'int')
functions.c:11:45: error: invalid type argument of unary '*' (have 'int')
Helloyeaaaaaaaaaaaaa
New error:
functions.c:11:3: warning: passing argument 2 of 'new_hash' makes pointer from integer without a cast [enabled by default]
hash.h:29:13: note: expected 'int (*)(char *)' but argument is of type 'int'
functions.c:11:3: warning: passing argument 3 of 'new_hash' makes pointer from integer without a cast [enabled by default]
hash.h:29:13: note: expected 'int (*)(void *, void *)' but argument is of type 'int'

If you want to pass a function as a function-pointer, simply provide the name:
new_hash(15, print_test, comp_func);
or alternatively (and equivalently), use the & symbol to make it clear what's going on:
new_hash(15, &print_test, &comp_func);

You should declare function before using it. If you don't do this, the compiler assumes that it returns int, and gives you an error when you try to dereference it (since it's impossibole to dereference int).
EDIT:
you may also misunderstood the concept of function pointers. you should not pass the result of print_test(word) to new_hash - you should pass print_test itself. (also, change its return type)

Related

how to print value which pointer member pointing to in C

I have a struct
struct c
{
int *id;
int type;
} obj;
how to print what obj.id pointing to? and also point obj->id to some int variable
I tried
printf("%p\n",obj.id);
but above is printing some address
and
printf("%d\n",obj.id);
in above compiler gives warning
format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’
Since obj.id is a pointer to an int (an int*) you need to dereference it (using the * operator).
Full example:
#include <stdio.h>
struct c {
int *id;
int type;
} obj;
int main() {
int x = 10;
obj.id = &x;
printf("%d\n", *obj.id);
}
You need to dereference the pointer:
printf("%d\n",*(obj.id));

incompatible types when assigning to type ‘struct ZipperNode’ from type ‘ZipperTree’

So, I'm getting this gcc compilation error when compiling:
zipper.c: In function ‘fillZipperInfo’:
zipper.c:384:22: error: incompatible types when assigning to type ‘struct ZipperNode’ from type ‘ZipperTree’
forest[current++] = n;
Here's the opaque type definition on the "zipper.h" file:
typedef struct ZipperNode *ZipperTree;
And here the ZipperNode definition on the "zipper.c" file:
struct ZipperNode {
int count;
ZipperTree left;
ZipperTree right;
Symbol symbol;
};
And the surrounding section where the error is being called:
ZipperTree forest = malloc(sizeof(ZipperTree) * ft->total);
int current = 0;
int i;
for(i = 0; i < ft->size; i++) {
if(ft->symbols[i] > 0) {
ZipperTree n = malloc(sizeof(ZipperTree));
n->count = ft->symbols[i];
n->symbol = i;
forest[current++] = n; //here!!
}
}
And here's the ft type, FreqTable, just in case, which is also pre-defined on "zipper.h":
struct FreqTable {
int symLength;
size_t size;
Symbol* symbols;
int total;
};
And I think this might be all I need to make the following question: what might be causing the error at the start of the post?
Thanks for your answers.
By replacing the ZipperTree types with ZipperNode * is becomes easier to see what is going wrong
ZipperNode *forest = malloc(sizeof(ZipperNode *);
ZipperNode *n = malloc(sizeof(ZipperNode *));
forest[current++] = n;
forest[current++] is your lvalue which, when indexing, is going to be the value pointed to, a ZipperNode, not a ZipperNode * which is what your rvalue is.
Compiling with clang gives a little more information but ultimately it is complaining about the same thing.
error: assigning to 'struct ZipperNode' from incompatible type 'ZipperTree'
(aka 'struct ZipperNode *'); dereference with *
forest[current++] = n; //here!!
^ ~
*
You are assigning a pointer to a non-pointer type. Try dereferencing n

pointer inside struct to dynamic 2-D array

Hope you can help me since I'm a little desperate right now. Im working with threads and I want them all to modify the same 2D array. So I made a struct with a pointer to the 2D array, but it isn't working. This is my code
typedef struct {
char XY;
int b;
int d;
int f;
int h;
} celdaMatriz;
typedef struct {
int totalX;
int totalY;
celdaMatriz **matriz;
char direction;
int i;
int j;
int cont;
} parameter;
As you can see parameter has the variable " celdaMatriz matriz**" (I'm sorry about the spanish in my code). Now comes a function to initialize a "celdaMatriz" 2D array
void createMatriz(int totalX, int totalY, celdaMatriz **matriz[totalX][totalY])
{
int i,j;
for(i=0;i<totalX; i++){
for(j=0; j<totalX;j++){
matriz[i][j]->XY=' ';
matriz[i][j]->b=0;
matriz[i][j]->d=0;
matriz[i][j]->f=0;
matriz[i][j]->h=0;
}
}
matriz[0][3]->XY='/';
matriz[2][0]->XY='*';
matriz[2][1]->XY='*';
matriz[0][2]->XY='*';
matriz[2][2]->XY='*';
matriz[1][3]->XY='*';
matriz[3][3]->XY='*';
}
the function createMatriz will change, but that's the idea. So now my main function
int main( int argc,char *argv[])
{
int i,j;
celdaMatriz **matriz = malloc( sizeof (*matriz) * 4);
for (i=0; i < 4; ++i)
matriz[i] = malloc(sizeof (**matriz) * 4);
crateMatriz(4,4,matriz);
parameter *p1,p2;
parameter *p1 = malloc(sizeof(*p1));
p1->totalX=4;
p1->totalY=4;
p1->i=0;
p1->j=0;
p1->cont=0;
p1->direction= 'f';
p1->matriz= matriz;
return 0;
}
So anytime I want to create a new thread I create a new parameter variable and its "matriz" variable is a pointer to the 2D array I created in the main function. Well at least that's the idea, but I get these errors
**request for member 'XY' in something not a structure or union**
**request for member 'b' in something not a structure or union**
**request for member 'd' in something not a structure or union**
**request for member 'f' in something not a structure or union**
**request for member 'h' in something not a structure or union**
passing argument 3 of 'crearMatriz' from incompatible pointer type [enabled by default]
main.c: 59:6: note: expected 'struct celdaMatriz ** (*) [(unsigned int) (totaly)]' but argument is of type 'struct celdaMatriz **
The errors come from the createMatrix function and the last one from the main function. By the way I'm using linux and C.
Thanks. Hope you can help me.
EDITED
I just fixed an error, this
*passing argument 3 of 'crearMatriz' from incompatible pointer type [enabled by default]
main.c: 59:6: note: expected 'struct celdaMatriz * () [(unsigned int) (totaly)]' but argument is of type 'struct celdaMatriz *
is already fixed. So the problem now is that I'm accessing matriz[i][j]->XY=' '; incorrectly
Hope you can help me since I'm a little desperate right now. Im working with threads and I want them all to modify the same 2D array. So I made a struct with a pointer to the 2D array, but it isn't working. This is my code
typedef struct {
char XY;
int b;
int d;
int f;
int h;
} celdaMatriz;
typedef struct {
int totalX;
int totalY;
celdaMatriz **matriz;
char direction;
int i;
int j;
int cont;
} parameter;
As you can see parameter has the variable " celdaMatriz matriz**" (I'm sorry about the spanish in my code). Now comes a function to initialize a "celdaMatriz" 2D array
void createMatriz(int totalX, int totalY, celdaMatriz **matriz[totalX][totalY])
{
int i,j;
for(i=0;i<totalX; i++){
for(j=0; j<totalX;j++){
matriz[i][j]->XY=' ';
matriz[i][j]->b=0;
matriz[i][j]->d=0;
matriz[i][j]->f=0;
matriz[i][j]->h=0;
}
}
matriz[0][3]->XY='/';
matriz[2][0]->XY='*';
matriz[2][1]->XY='*';
matriz[0][2]->XY='*';
matriz[2][2]->XY='*';
matriz[1][3]->XY='*';
matriz[3][3]->XY='*';
}
the function createMatriz will change, but that's the idea. So now my main function
int main( int argc,char *argv[])
{
int i,j;
celdaMatriz **matriz = malloc( sizeof (*matriz) * 4);
for (i=0; i < 4; ++i)
matriz[i] = malloc(sizeof (**matriz) * 4);
crateMatriz(4,4,matriz);
parameter *p1,p2;
parameter *p1 = malloc(sizeof(*p1));
p1->totalX=4;
p1->totalY=4;
p1->i=0;
p1->j=0;
p1->cont=0;
p1->direction= 'f';
p1->matriz= matriz;
return 0;
}
So anytime I want to create a new thread I create a new parameter variable and its "matriz" variable is a pointer to the 2D array I created in the main function. Well at least that's the idea, but I get these errors
**request for member 'XY' in something not a structure or union**
**request for member 'b' in something not a structure or union**
**request for member 'd' in something not a structure or union**
**request for member 'f' in something not a structure or union**
**request for member 'h' in something not a structure or union**
passing argument 3 of 'crearMatriz' from incompatible pointer type [enabled by default]
main.c: 59:6: note: expected 'struct celdaMatriz ** (*) [(unsigned int) (totaly)]' but argument is of type 'struct celdaMatriz **
The errors come from the createMatrix function and the last one from the main function. By the way I'm using linux and C.
Thanks. Hope you can help me.
EDIT
I just fixed an error, this
*passing argument 3 of 'crearMatriz' from incompatible pointer type [enabled by default]
main.c: 59:6: note: expected 'struct celdaMatriz * () [(unsigned int) (totaly)]' but argument is of type 'struct celdaMatriz *
is already fixed. So the problem now is that I'm accessing matriz[i][j]->XY=' '; incorrectly
EDIT
Hi. I just want to let you know that I already found an answer to my problem. Instead of send a pointer to the matrix, I will use it as a global variable, that way all the threads will be able to modify it. So the solution is 1- Declare a global celdaMatriz **matriz
celdaMatriz **matriz;
Next I changed the memory allocation
matriz = (celdaMatriz **) malloc(4 * sizeof(celdaMatriz *));
for (i = 0; i < 4; ++i)
{
matriz[i] = (celdaMatriz *) malloc(4 * sizeof(celdaMatriz));
}
Finally the new void createMatriz function:
void crearMatriz(int totalX, int totalY)
{
int i=0,j=0;
for(i=0; i<totalX;i++){
for(j=0; j<totalY; j++){
celdaMatriz *nodo = malloc(sizeof(celdaMatriz));
nodo->b=0;
nodo->d=0;
nodo->f=0;
nodo->h=0;
nodo->casilla=0;
matriz[i+j*totalY]=(celdaMatriz *)nodo;
}
}
matriz[12]->casilla=1;
for(i=0; i<totalX; i++){
for(j=0; j<totalY; j++){
printf(" %d ", matriz[i+j*totalY]->casilla);
}
printf("\n");
}
}
And that's it. Thanks to all of you who helped me with this problem
I guess that the problem is that you tried to call creatMatriz like this,
createMatriz(p1->totalX, p1->totalY, p1->matriz);
and C (C99) does not like it. The problem is that p1->matriz is of type struct celdaMatriz **, but your prototype of createMatriz asked for a struct * (*) [totalY] because C ignores [totalX].
If you want to keep the definition of parameter unchanged, I would suggest you just use a double pointer.

warning: initialisation from incompatible pointer type

Hi all it's been sometime since I've touched C so I'm really rusty on it. I wrote a small program to create a matrix using two dynamic arrays. However, I'm getting this warning and I don't understand why? I guess I'm not quite sure about pointers to pointers. Can someone help me point out where my problem is? Thanks.
sm.c: In function ‘main’:
sm.c:11:13: warning: initialisation from incompatible pointer type [enabled by default]
sm.c: In function ‘makeMatrix’:
sm.c:27:3: warning: return from incompatible pointer type [enabled by default]
#include <stdio.h>
#include <stdlib.h>
typedef int (**intptr) ();
intptr makeMatrix(int n);
int main(int argc, char *argv[]) {
int n = 2;
int **A = makeMatrix(n);
if(A) {
printf("A\n");
}
else printf("ERROR");
}
intptr makeMatrix(int size) {
int **a = malloc(sizeof *a * size);
if (a)
{
for (int i = 0; i < size; i++)
{
a[i] = malloc(sizeof *a[i] * size);
}
}
return a;
}
You've got some problems here:
typedef int (**intptr) ();
intptr makeMatrix(int n);
...
int **A = makeMatrix(n);
The intptr typedef declares a pointer to a pointer to a function that takes an indeterminate number of arguments and returns an int. A is not an int.
You need to write:
int **makeMatrix(int n);
int **A = makeMatrix(n);
Using a typedef won't help much here.
typedef int **(*intptr)();
That declares a pointer to a function that returns a pointer to a pointer to an int. But writing
intptr makeMatrix(int n);
would declare that makeMatrix() returns a pointer to a function, not an int **.
Your typedef has an extra (), making it a zero argument function type. Remove that and you should be good.

How do I call an arbitrary C function passed to another function?

I'm writing a unit test framework (see SO for more details). Or view the code at GitHub.
Safer Code describes a way to pass functions of arbitrary types.
But how do I call such a function without knowing its types beforehand? Assume f needs no input, so f() should work on its own.
Let's say I want to populate an array using an arbitrary generator function.
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = gen(NULL);
}
return arr;
}
It should look something like this, but I get compiler errors:
gcc -o example example.c qc.c qc.h -lgc
In file included from example.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
In file included from qc.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
qc.c:23: error: conflicting types for ‘gen_array’
qc.h:21: error: previous declaration of ‘gen_array’ was here
qc.c: In function ‘gen_array’:
qc.c:29: warning: dereferencing ‘void *’ pointer
qc.c:29: error: too many arguments to function ‘gen’
qc.c:29: error: invalid use of void expression
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
make: *** [example] Error 1
After thinking about some more I realize your problem your above code would never work.
You are first calling trying to call a void function with no parameters with the parameter NULL. Next you would need your code to be more generic. I placed an example below of what I mean. Now using a global variable
#include <stdio.h>
#include <stdlib.h>
typedef void (*fp)(void);
void * GEN_ARRAY_TEMP;
int gen_int() {
return 67;
}
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = malloc(len * size);
void* arr_end = arr + len * size;
GEN_ARRAY_TEMP = arr;
while (GEN_ARRAY_TEMP <= arr_end) {
gen();
GEN_ARRAY_TEMP+=size;
}
return arr;
}
void make_int() {
(*(int*)GEN_ARRAY_TEMP) = 9;
}
int main() {
int i;
int * gen_int_array = (int*) gen_array(make_int, sizeof(int));
for(i=0;i<67;i++) {
printf("%d\n",gen_int_array[i]);
}
}
That page suggests you make the function pointer take a void*. So in order for your code to compile, you must pass it a void pointer:
typedef void* (*fp)(void*);
doit(fp f) {
f(NULL);
}
And just make sure that the function that you're calling simply ignores the parameter.
Generally speaking, these generic function pointers are used for starting threads. The void pointer is simply a pointer to a struct that holds the actual parameters.
What would you need to do is wrap your function in a void function like so
#include <stdio.h>
typedef void (*fp)(void);
int sum(int x,int y) {return x+y;}
void doit(fp f) {
f();
}
void func() {
printf("Hello %d\n",sum(1,2));
}
int main() {
doit(func);
}
You have two problems:
First, qc.h is missing a <stdlib.h> include. This is needed for use of size_t.
Second, in gen_array, you create a void *arr, then try to dereference it as an array (arr[i]). Since the compiler doesn't know the size of your array elements, it cannot fill the array. You must treat it as a char *, offset by arr + size * i, and pass it into gen rather than taking a return (returns also need to know the structure size):
// ...
char *arr = GC_MALLOC(len * size);
for (int i = 0; i < len; i++) {
gen(arr + i * size, NULL);
}
return arr;
This will of course require changing the fp type definition.
For the case where your pointer to a function 'fp' is of type which takes no argument and returns void, in which case you should declare it as :
typedef void (*fp)();
In the above case the call should be :
(*gen)();
If your pointer to the function 'fp' is of type which takes 'void *' as argument and returns void, in which case you should declare it as :
typedef void (*fp)(void *);
In the above case the call should be :
(*gen)(NULL);
or any other pointer variable you might want to pass.
As far as your example goes try this :
typedef void * (*fp)(void *);
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = (*gen)(NULL);
}
return arr;
}

Resources