EDIT: This has been answered with the help of John Bollinger and alk. Read their comments below! I've also included my revised code at the bottom on this original post for anyone searching to read
I'm trying to use an array of function pointers to send as the function argument in pthread_create but when I try to compile (using: "gcc -std=c99 P1.c -lpthread" I am getting the following errors:
P1.c:40:1: warning: initialization from incompatible pointer type [enabled by default]
func_ptr funcs[4] = {func0, func1, func2, func3};
P1.c:40:1: warning: (near initialization for 'funcs[0]') [enabled by default]
P1.c:40:1: warning: initialization from incompatible pointer type [enabled by default]
P1.c:40:1: warning: (near initialization for 'funcs[1]') [enabled by default]
P1.c:40:1: warning: initialization from incompatible pointer type [enabled by default]
P1.c:40:1: warning: (near initialization for 'funcs[2]') [enabled by default]
P1.c:40:1: warning: initialization from incompatible pointer type [enabled by default]
P1.c:40:1: warning: (near initialization for 'funcs[3]') [enabled by default]
I think it's an issue with my typedef declaration of my function pointer but I'm having trouble figuring out exactly what the issue is. Below is the relevant code snippet:
void func0()
{ printf("A"); }
void func1()
{ printf("B"); }
void func2()
{ printf("C"); }
void func3()
{ printf("D"); }
typedef void* (*func_ptr)(void *);
func_ptr funcs[4] = {func0, func1, func2, func3};
int main(int argc, char *argv[])
{
pthread_t pth[THREADCNT];
for(int i =0; i < THREADCNT; i++)
pthread_create(&pth[i], NULL, (funcs[i])(), NULL);
for(int i =0; i < THREADCNT; i++)
pthread_join(pth[i], NULL);
}
REVISED WORKING CODE BELOW
// changed these functions to void* with (void * pv) parameter to
// match the typedef (and also match the pthread_create parameter)
void* func0(void * pv)
{ printf("A"); }
void* func1(void * pv)
{ printf("B"); }
void* func2(void * pv)
{ printf("C"); }
void* func3(void * pv)
{ printf("D"); }
typedef void* (*func_ptr)(void *);
func_ptr funcs[4] = {func0, func1, func2, func3};
int main(int argc, char *argv[])
{
pthread_t pth[THREADCNT];
for(int i =0; i < THREADCNT; i++)
pthread_create(&pth[i], NULL, funcs[i], NULL);
// changed the funcs[i] because the function isn't called, the value is just passed as an argument
for(int i =0; i < THREADCNT; i++)
pthread_join(pth[i], NULL);
}
Change
void func0()
to be
void * func0(void * pv)
(same for the other three)
because that's the type the array is defined to hold, as well as the type pthread_create() expects.
Change
pthread_create(&pth[i], NULL, (funcs[i])(), NULL);
to be
pthread_create(&pth[i], NULL, funcs[i], NULL);
as you do not want to call funcs[i] but pass its value.
Related
I am running the below code and it is working fine but still it is giving some warning which i don't understand. Can someone please explain this to me ? Thanks
#include <stdio.h>
#include <pthread.h>
void* the_thread_func(double data_for_thread[]) {
/* Do something here? */
for(int i=0;i<3;i++){
double sum = sum + data_for_thread[i];
printf("The sum done by the_thread_func() is = %f\n",sum);
}
return NULL;
}
int main() {
printf("This is the main() function starting.\n");
double data_for_thread[3];
data_for_thread[0] = 5.7;
data_for_thread[1] = 9.2;
data_for_thread[2] = 1.6;
/* Start thread. */
pthread_t thread;
printf("the main() function now calling pthread_create().\n");
pthread_create(&thread, NULL, the_thread_func, data_for_thread);
printf("This is the main() function after pthread_create()\n");
/* Do something here? */
for(int i=0;i<3;i++){
double sum = sum + data_for_thread[i];
printf("The sum done by main() is = %f\n",sum);
}
/* Wait for thread to finish. */
printf("the main() function now calling pthread_join().\n");
pthread_join(thread, NULL);
return 0;
}
warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types] pthread_create(&thread, NULL, the_thread_func, data_for_thread);
^~~~~~~~~~~~~~~
In file included from thread_data.c:2:0:
/usr/include/pthread.h:234:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘void * (*)(double *)’
extern int pthread_create (pthread_t *__restrict __newthread,
According to the manual pthread_create needs to be given a function with this signature:
void* (*start_routine)(void*)
But you are passing it a function that accepts double*here:
void* the_thread_func(double data_for_thread[]) // decays to double*
I think you need to change the signature and cast the void*inside the function like this:
// accept void*
void* the_thread_func(void* vp) {
/* Do something here? */
double* data_for_thread = reinterpret_cast<double*>(vp); // cast here
for(int i=0;i<3;i++){
double sum = sum + data_for_thread[i];
printf("The sum done by the_thread_func() is = %f\n",sum);
}
return nullptr;
}
So this simple case just prints out 3 when passing a function:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_1_fn_a(int fn_x(int, int)) {
return fn_x(1, 2);
}
int
main() {
int x = case_1_fn_a(add);
printf("%d\n", x);
return 0;
}
But now I would like to pass a function to a function. How do I do that?
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
return add(fn_x(add, add), fn_y(add, add));
}
int
case_2_fn_b(int fn_x(int, int)) {
return fn_x(1, 2);
}
int
main() {
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
printf("%d\n", x);
return 0;
}
But I get these errors (I get all kinds of different errors if I try adjusting this or that thing, so nothing works):
tmp.c:11:19: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:24: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:35: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:11:40: warning: incompatible pointer to integer conversion passing 'int (int, int)' to parameter of type 'int' [-Wint-conversion]
return add(fn_x(add, add), fn_y(add, add));
^~~
tmp.c:21:23: warning: incompatible pointer types passing 'int (int (*)(int, int))' to parameter of type 'int (*)(int, int)'
[-Wincompatible-pointer-types]
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
^~~~~~~~~~~
tmp.c:10:17: note: passing argument to parameter 'fn_x' here
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
^
tmp.c:21:36: warning: incompatible pointer types passing 'int (int (*)(int, int))' to parameter of type 'int (*)(int, int)'
[-Wincompatible-pointer-types]
int x = case_2_fn_a(case_2_fn_b, case_2_fn_b);
^~~~~~~~~~~
tmp.c:10:37: note: passing argument to parameter 'fn_y' here
case_2_fn_a(int fn_x(int, int), int fn_y(int, int)) {
^
6 warnings generated.
Segmentation fault: 11
Essentially I want to pass a series of functions to function "A", and then have function "A" take those functions (let's call them functions "B", "C", and "D"), and call them with a few functions as parameters. Functions "B", "C" and "D" then take their function arguments, and pass simple values to them like integers or chars.
First, when passing functions as parameters, you typically want to use function pointers instead. So instead of this as a parameter:
int fn_x(int, int)
You would use this:
int (*fn_x)(int, int)
Now for the main problem: functions (and function pointers) as parameters and return values can have confusing syntax. Creating typedefs for function pointers greatly simplifies this.
So let's make the following typedefs:
typedef int (*addfunc)(int, int);
typedef int (*fnb)(addfunc);
typedef int (*fna)(fnb, fnb);
So now you have:
int
case_2_fn_a(fnb fn_x, fnb fn_y) {
return add(fn_x(add), fn_y(add));
}
int
case_2_fn_b(addfunc fn_x) {
return fn_x(1, 2);
}
As you can see, the syntax is much cleaner. It's also more apparent that the body of case_2_fn_a had a error where fn_x and fn_y were being passed two parameters instead of one.
If you really wanted to do this without typedefs, case_2_fn_a would look like this:
int
case_2_fn_a(int (*fn_x)(int (*)(int,int)), int (*fn_y)(int (*)(int,int))) {
return add(fn_x(add), fn_y(add));
}
As said in the comments, use function pointers:
Case 1:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_1_fn_a(int(*fn_x)()) {
return (*fn_x)(1, 2);
}
int
main() {
int x = case_1_fn_a(&add);
printf("%d\n", x);
return 0;
}
Case 2:
#include <stdio.h>
int
add(int a, int b) {
return a + b;
}
int
case_2_fn_a(int (*fn_x)(), int(*fn_y)()) {
return add((*fn_x)(&add), (*fn_y)(&add));
}
int
case_2_fn_b(int(*fn_x)()) {
return (*fn_x)(1, 2);
}
int
main() {
int x = case_2_fn_a(&case_2_fn_b, &case_2_fn_b);
printf("%d\n", x);
return 0;
}
here is a snippet of a program I've been working on. Basically, I am getting the same error message twice as described by the title. This is my first time working with pthreads so if someone can tell me what I'm doing wrong I'd appreciate it.
#include <pthread.h>
#include <stdio.h>
void *User_choices();
void *Switch_statement(void *);
void *Server_function(void *);
pthread_t SEND_TO_SERVER_THREAD;
pthread_t PIC_COMMUNICATION_THREAD;
pthread_t USER_INTERFACE_THREAD;
char buf[1024];
void main()
{ // 1
snprintf(buf, 1024, "string");
while(1)
{ // 2
pthread_create(&USER_INTERFACE_THREAD, NULL, User_choices, NULL);
} // 3
} // 4
void *User_choices()
{ // 5
int userinput;
printf("Type 0 to reset sensor, 1 to ping, 2 to receive ADC value, 3 to quit the program: ");
scanf("%i", &userinput);
pthread_create(&PIC_COMMUNICATION_THREAD, NULL, Switch_statement, &userinput);
} // 6
void *Switch_statement((void *)userchoice))
{ // 7
int user = (int)*userchoice;
switch(user)
{ // 8
case 1:
printf("OTHER FUNCTIONS USUALLY GO HERE \n");
break;
case 2: //RETRIEVE ADC CASE
pthread_create(&SEND_TO_SERVER_THREAD, NULL, Server_function, (void *)&buffer);
break;
case 3:
exit(0);
case 0: //RESET CASE
printf("ONCE AGAIN, OTHER FUNCTIONS USUALLY GO HERE");
break; //EXIT THE PROGRAM
default:
printf("Your entry is not a valid option! Try again \n");
} // 9
} // 10
void *Server_function((void *)server_buffer))
{ // 11
const char* send_to_server = (char)*server_buffer;
HTTP_GET(send_to_server);
} // 12
Here are the error codes:
justpthread.c:31:24: error: expected declaration specifiers or ‘...’ before ‘(’ token
void *Switch_statement((void *)userchoice))
^
justpthread.c:53:23: error: expected declaration specifiers or ‘...’ before ‘(’ token
void *Server_function((void *)server_buffer))
If I change just void main to int main, I get the same two error codes. If i take out the parentheses surround (void *), no matter when it's int main or void main, i get the following:
justpthread.c: In function ‘Switch_statement’:
justpthread.c:33:18: warning: dereferencing ‘void *’ pointer [enabled by default]
int user = (int)*userchoice;
^
justpthread.c:33:2: error: invalid use of void expression
int user = (int)*userchoice;
^
justpthread.c:41:76: error: ‘buffer’ undeclared (first use in this function)
pthread_create(&SEND_TO_SERVER_THREAD, NULL, Server_function, (void *)&buffer);
^
justpthread.c:41:76: note: each undeclared identifier is reported only once for each function it appears in
justpthread.c:44:5: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
exit(0);
^
justpthread.c: In function ‘Server_function’:
justpthread.c:55:37: warning: dereferencing ‘void *’ pointer [enabled by default]
const char* send_to_server = (char)*server_buffer;
^
justpthread.c:55:2: error: invalid use of void expression
const char* send_to_server = (char)*server_buffer;
^
And you guys have me incredibly confused as far as the brackets go, so I numbered all of them. I'm seeing an even number, and they look like they alter directions properly.
Going off of additional recommendations, I changed my code like so:
void main()
{
snprintf(buf, 1024, "string");
while(1)
{
pthread_create(&USER_INTERFACE_THREAD, NULL, User_choices, NULL);
}
}
void *User_choices()
{
int userinput;
printf("Type 0 to reset sensor, 1 to ping, 2 to receive ADC value, 3 to quit the program: ");
scanf("%i", &userinput);
pthread_create(&PIC_COMMUNICATION_THREAD, NULL, Switch_statement, &userinput);
}
void *Switch_statement(void *userchoice)
{
int user = *((int*)userchoice);
switch(user)
{
case 1:
printf("OTHER FUNCTIONS USUALLY GO HERE \n");
break;
case 2: //RETRIEVE ADC CASE
pthread_create(&SEND_TO_SERVER_THREAD, NULL, Server_function, (void *)&buf);
break;
case 0: //RESET CASE
printf("ONCE AGAIN, OTHER FUNCTIONS USUALLY GO HERE");
break; //EXIT THE PROGRAM
default:
printf("Your entry is not a valid option! Try again \n");
}
}
I changed int user... to
int user = *((int*)userchoice);
as recommended, and so I got the following error messages:
justpthread.c: In function ‘Server_function’:
justpthread.c:53:37: warning: dereferencing ‘void *’ pointer [enabled by default]
const char* send_to_server = (char)*server_buffer;
^
justpthread.c:53:2: error: invalid use of void expression
const char* send_to_server = (char)*server_buffer;
So it looks like it got rid of some of the previous errors. So I noticed now that server_buffer is having issues as well so I tried to change that to:
void *Server_function(void *server_buffer)
{
const char* send_to_server = *((char*)server_buffer);
//HTTP_GET(send_to_server);
}
And now I just have one error:
justpthread.c: In function ‘Server_function’:
justpthread.c:53:31: warning: initialization makes pointer from integer without a cast [enabled by default]
const char* send_to_server = *((char*)server_buffer);
For the last warning, you want to cast void* to char*, but with *((char*)server_buffer you are dereferencing pointer to server_buffer and casting void* to char and not to char*.
The proper way is:
const char* send_to_server = (char*)server_buffer;
Remove the (parenthesis) around void * on those lines.
Try void *userchoice and
int user = *((int*)userchoice);
You cannot do anything with void * before you cast it.
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)
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.