Passing a function with void pointer as argument gives warning - c

I implemented a queue and want a function that prints its elements, regardless of the type. So I made a function printQueue as follows:
void printQueue(queue_t *queue, void (*f)(void *)) {
node_t *node = (*queue).front;
while(node != NULL) {
(*f)(node->item);
puts("");
node = (*node).next;
}
}
The idea is that it will receive the queue, and a function to print an element from the queue (the queue was implemented to be able to hold any kind of element). So this function would iterate the queue and call that function to print each of it's elements.
Then I made a function to print arrays of ints which contain their own size in it's first element as follows:
void printSpecialIntArray(int *array) {
int i;
for(i=0; i<array[0]; i++) {
printf("%d ", array[i]);
}
}
However if I initialize a queue say Q with that kind of arrays and call printQueue(Q, printSpecialIntArray) it seems to work as intended but I get a warning:
warning: passing argument 2 of ‘printQueue’ from incompatible pointer type [-Wincompatible-pointer-types]
printQueue(Q, printSpecialIntArray);
^~~~~~~~~~~~
In file included from main.c:3:0:
queue.c:32:6: note: expected ‘void (*)(void *)’ but argument is of type ‘void (*)(int *)’
void printQueue(queue_t *queue, void (*f)(void *)) {
Why does this warning happen and how can it be fixed? Is there a cleaner way to do this?
Also if you're wondering, I'm using an array which has it's own size as an element because I'm implementing a process simulator, and those "Special int arrays" are actually supposed to represent a process. If you know a cleaner way to do that I would also appreciate if you include in your answer/comment.

The error message is very straight forward. The function void printQueue(queue_t *queue, void (*f)(void *)) expects f to be a pointer to a function returning void and taking exactly one argument and its type should be void*. The function printSpecialIntArray does not fulfill this, since it's argument is int*.
One solution is to change f so that it takes int* as argument instead of void*. Another solution is to rewrite printSpecialIntArray:
void printSpecialIntArray(void *a) {
int *array = (int*) a;
int i;
for(i=0; i<array[0]; i++) {
printf("%d ", array[i]);
}
}
Note:
Even though a void pointer can be safely promoted to an int pointer, the function f still needs to be a function that takes a void pointer as argument. It's not the argument that's the problem, it's the function declaration itself.

Your function signature does not match.
You need to provide the expected signature and cast the pointer according to your needs:
void printSpecialIntArray(void *arr) {
int array = (int *)arr;
int i;
for(i=0; i<array[0]; i++) {
printf("%d ", array[i]);
}
}

Related

How to fix "conflicting types" for a function and its declaration?

I want to pass a two-dimensional char array to a function but don't know how to declare the function before the main(). The function compiles and works well before I declare it. But after I declare it, I encounter compiling issues.
I'm using EMACS on MacBook pro. The compiler is gcc.I tried to declare my function print string various ways including
void printstring(int, int,char **);
or
void printstring(int, int,char *);
But none of them work. My Full codes are:
#include<stdio.h>
#include<stdlib.h>
void printstring(int, int,char **);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
I expected that there is no compiling error but I got one error and one warning. Details can be found below:
test.c: In function 'main':
test.c:9:19: warning: passing argument 3 of 'printstring' from incompatible pointer type [-Wincompatible-pointer-types]
printstring(3,6,word);
^~~~
test.c:5:6: note: expected 'char **' but argument is of type 'char (*)[6]'
void printstring(int, int,char **);
^~~~~~~~~~~
test.c: At top level:
test.c:13:6: error: conflicting types for 'printstring'
void printstring(int n, int m, char (*w)[m]){
^~~~~~~~~~~
test.c:5:6: note: previous declaration of 'printstring' was here
void printstring(int, int,char **);
^~~~~~~~~~~
the problem is that you're using a variable length array. The last argument (the list of strings) depends on the second argument (m). And char ** is not suitable, as it's just a pointer on pointers. So the max dimension of the strings would be lost when iterating on the 2D array.
Use a standard forward declaration, copying exactly the real declaration if you don't want to put the function before the main one.
void printstring(int n, int m, char (*w)[m]);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
If you have read-only strings, I suggest that you use a standard array of constant pointers instead:
void printstring(int n, const char *w[]);
int main(){
const char *word[] = {"hello","world","I"};
printstring(3,word);
return 0;
}
void printstring(int n, const char *w[])
{
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
note that
printstring(3,word);
can be replaced by
printstring(sizeof(word)/sizeof(word[0]),word);
before array decays to pointer (that autocomputes the number of strings)
If you want to maintain a name free declaration for whatever reason, you can use the * notation (reserved to function prototype scope) for the variably modified type
void printstring(int, int,char (*)[*]);
Still a VLA, and in fact, exactly equivalent to the notation that uses m. Though, ostensibly, it may convey intent not as clearly as using m in the forward declaration.
The following should just work:
void printstring(int n, int m, char (*w)[m]);
The function prototype and definition should be kept identical, except maybe for certain qualifiers such as const and default arguments in C++.
char** cannot be used to point at 2D arrays, it can only be used to point at the first element of a 1D array of char*, which is something else.
Your compiler error is from having non-matching declaration and definition. Correct code:
void printstring(int n, int m, char w[n][m]);
...
void printstring(int n, int m, char w[n][m]){
...
}
Alternatively, you can write void printstring(int n, int m, char (*w)[m]) and it is completely equivalent. But that is just harder to read, so why would you?

passing address of an array in a function for initialization

Hi im trying to use a function to initialize an array with random number. somehow i get this error that i couldnt be able to solve
void arrayInit(int *A, int n){
int i;
for ( i = 0; i < n; ++i)
{
A[i] = rand();
}
}
call arrayInit() in main
int main(void){
int array1[1000];
arrayInit(&array1, 1000);
return 0;
}
I get error saying:
csort.c:62:13: warning: passing argument 1 of ‘arrayInit’ from incompatible pointer type
arrayInit(&array1, 1000);
^
csort.c:8:6: note: expected ‘int *’ but argument is of type ‘int (*)[1000]’
void arrayInit(int *A, int n){
^
You need the call for arrayInit to be like this:
arrayInit(array1, 1000);
Instead of this:
arrayInit(&array1, 1000);
The name of an array decays to be a pointer to the first element, which is what your function needs.
When you have
int array1[1000];
The type of &array1 is int (*)[1000], which is not what arrayInit expects. By using
arrayInit(arra1, 1000);
you are letting compiler decay the array to a pointer, which of of type int* in your case.
An array does not decay to a pointer in couple of cases:
When you use the & operator.
When you use the sizeof operator.
The identifier of any array is a type * itself.
So you need to call your function like this:
arrayInit(array1, 1000);.
Calling your function with an address of a pointer(&array1) would require a int** A(a pointer to a pointer type) in your function definition, which is certainly not the thing to do in this case, since the indexing in this case would also give an error.
you can call arrayInit() using the '&' as:
arrayInit(&array1[0], 1000);

incompatible pointer type in C

so I'm trying to pass a type double * to a function that accepts void ** as one of the parameters. This is the warning that I am getting.
incompatible pointer type passing 'double **' to parameter of type 'void **'
Here is a snippet of my code.
int main( void )
{
// Local Declaration
double *target;
// Statement
success = dequeue(queueIn, &target);
}
Here's the prototype declaration of the function.
int dequeue ( QUEUE *queue, void **dataOutPtr );
I thought that if I passed target as a two level pointer that it would work, but I guess I'm wrong. Can someone please explain to me how come i'm getting this warning?
Even though all other pointer types can be converted to and from void * without loss of information, the same is not true of void ** and other pointer-to-pointer types; if you dereference a void ** pointer, it needs to be pointing at a genuine void * object1.
In this case, presuming that dequeue() is returning a single pointer value by storing it through the provided pointer, to be formally correct you would need to do:
int main( void )
{
void *p;
double *target;
success = dequeue(queueIn, &p);
target = p;
When you write it like this, the conversion from void * to double * is explicit, which allows the compiler to do any magic that's necessary (even though in the overwhelmingly common case, there's no magic at all).
1. ...or a char *, unsigned char * or signed char * object, because there's a special rule for those.
In your prototype declaration , you said second argument as void** ,so you have to type cast double** to void**.
Instead of this line success = dequeue(queueIn, &target);.
Call like this success = dequeue(queueIn,(void**) &target);
int main( void )
{
// Local Declaration
double *target;
// Statement
success = dequeue(queueIn, (void**)&target);
}
Use it like this.

How do I realloc an array of function pointers?

Straight to the code:
#define PRO_SIGNAL( func, param ) (*func)(param)
void PRO_SIGNAL( paint[0], Pro_Window* );
signal->paint = realloc( signal->paint, sizeof( void (*)(Pro_Window*) ) * signal->paint_count );
The Error:
error: incompatible types when assigning to type 'void (*[])(struct Pro_Window *)' from type 'void *'|
It appears that you are assigning to an array not a pointer.
From your output error message:
'void (*[])(struct Pro_Window *)' from type 'void *'|
Note the [] in there (and it certainly isn't a lambda!) rather than a *
If this is an "extendable" struct you need to realloc the entire struct not just the array member.
By the way, a tip: if realloc fails it returns a NULL pointer and if you assign it to the variable that was being realloc'ed, the original memory it was pointing to will be lost forever. So always realloc into a temp first, check the value, and then assign back to the original pointer if it worked.
You don't show us the definition of singal->paint, but I infer from the error message that it's declared as an array of function pointers, meaning signal is a struct with a flex array (paint[]). You can't assign to an array, you need to realloc the whole struct.
Not sure what you're trying to do, but this works perfectly here:
#include <stdlib.h>
int main(int argc, char ** argv)
{
void (**foobar) (int a, int b);
void (**tmp) (int a, int b);
foobar = NULL;
if (!(foobar = malloc(sizeof(*foobar)*4))
return 1;
if (!(tmp = realloc(foobar, sizeof(*foobar)*5)) {
free(foobar);
return 1;
} else {
foobar = tmp;
}
free(foobar);
return 0;
}
So, either you're trying to realloc an array like Kevin says, or perhaps you're compiling in C++ mode, where I believe that the cast is not implicit.
Edit: I've added some error handling.

c language array problems

Hi
I'm new to c language i hava a problem :
i want to send a 2-d array to a function via pointer.
The function should return pointer to 2-d array.
I wrote the following code for this :
#include<stdio.h>
int* put(int *b);
int main()
{
int a[2][3],i,j;
system("clear");
put(a);
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
printf("\na[%d][%d]= %d",i,j,a[i][j]);
}
}
return 0;
}
int* put(int *b)
{
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
b[i][j]=i;
}
}
return b;
}
when i compile it with gcc2de.c it shows following errors :
2de.c: In function ‘main’:
2de.c:9: warning: passing argument 1 of ‘put’ from incompatible pointer type
2de.c:3: note: expected ‘int *’ but argument is of type ‘int (*)[3]’
2de.c: In function ‘put’:
2de.c:28: error: subscripted value is neither array nor pointer
2de.c: In function ‘main’:
2de.c:32: error: expected declaration or statement at end of input
Than i just change the code of function which is following :
#include<stdio.h>
int* put(int **b);
int main()
{
int a[2][3],i,j;
system("clear");
put(a);
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
printf("\na[%d][%d]= %d",i,j,a[i][j]);
}
}
return 0;
}
int* put(int **b)
{
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
b[i][j]=i;
}
}
return b;
}
when i complie it i got following errors:
2de.c: In function ‘main’:
2de.c:9: warning: passing argument 1 of ‘put’ from incompatible pointer type
2de.c:3: note: expected ‘int **’ but argument is of type ‘int (*)[3]’
2de.c: In function ‘put’:
2de.c:31: warning: return from incompatible pointer type
2de.c: In function ‘main’:
2de.c:32: error: expected declaration or statement at end of input
2de.c: In function ‘main’:
2de.c:9: warning: passing argument 1 of ‘put’ from incompatible pointer type
2de.c:3: note: expected ‘int **’ but argument is of type ‘int (*)[3]’
2de.c: In function ‘put’:
2de.c:31: warning: return from incompatible pointer type
2de.c: In function ‘main’:
2de.c:32: error: expected declaration or statement at end of input
what I'm doing wrong ?
can anybody tell me what is the way to pass 2d-array via pointers to a function ?
can anybody tell me how to return two d array via pointer in a function
The first error that you have is that you are not passing a correct type as declared by your function. So to clean up your code with the least amount of corrections, it would probably look something like this:
#include<stdio.h>
void put(int *b);
int main()
{
int a[2][3],i,j;
put(&a[0][0]);
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
printf("\na[%d][%d]= %d", i, j, a[i][j]);
}
}
printf("\n\n");
system("PAUSE"); // Not recommended, but works for now
return 0;
}
void put(int *b)
{
int count = 1;
int i, j;
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
//b[i][j]=i;
*(b + ((i*3) + j)) = count++;
}
}
}
The two major corrections are:
You pass in the start address of your 2-D array explicitly by addressing it as &a[0][0].
Also, note the pointer arithmetic that you'll have to use when you use an int *b as well.
Note also that since you're passing in a pointer, you're modifying the value at that address location. Thus there is no need to return a pointer back at all.
Hope it helps. Cheers!
where are you storing the return value from put ?
the declaration should be int** put( int **) according yo your code.
The first error you have is that you are trying to define a function inside another function. The simplest thing to do is to just define put where you declare it:
int put()
{
/* definition of put */
}
int main()
{
/* body calls put */
}
The second problem is that in neither code snippet are you passing a compatible parameter to put.
If you want to pass a to a function then you should note that arrays as arguments always decay to a pointer to their first element.
a has type int [2][3], i.e. an array of 2 arrays of 3 ints. This will decay to a pointer to an array of 3 ints or int (*)[3]. This should explain the compile error that you are getting. You should declare put either as:
void put(int (*b)[3]);
or as the completely equivalent:
void put(int b[][3]);
Because you cannot pass arrays by value the compiler will automatically convert a function declaration which takes an array parameter to one which takes the equivalent pointer parameter.
I've changed the return type to void as you don't use or need the return value as you are passing the parameter by pointer. You should remove return b; from your definition of put.
Hint: Don't think of int[2][3] as a 2-d array but as an array of arrays.
You can not return a 2d-array from a function in C, you can only return a 1d-array of pointers to the first elements of a 2d-array.
Maybe you could find useful this:
Pass 2d array to function in C?
or this:
C++ Returning multidimension array from function
1.you should declare or define the function before use it,it's different with other popular luanguage.
2.you do not need to return the pointer in the function put ,the data in array has be changed
3.you needed to notice the type ,the type of int array[][] is int **

Resources