C++ typecast error [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
void pointers: difference between C and C++
Hi I have the following function:
void task2(int a)
{
printf(" Task 2 running..\n");
sleep(2);
printf(" Task 2 exiting..\n");
}
thpool_add_work(threadpool, (void*)task2, (void*)a);
int thpool_add_work(thpool_t* tp_p, void *(*function_p)(void*), void* arg_p)
{
// some code here
}
The above code works well with C, but does not compile in C++. I'm getting the following error:
error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
error: initializing argument 2 of ‘int thpool_add_work(thpool_t*, void* (*)(void*), void*)’
I'm not able to figure out the reason for this error. Any idea why this error crops up when I change the file extension to CPP and compile?

You have to change the signature of task2 to match the type of the thpool_add_work argument:
void* task2(void* a)
The call which creates the thread would become
thpool_add_work(threadpool, task2, &a);
assuming that a is int.
If you need to use the argument of task2, you could do following:
int ia = *(int*)a;
Update to answer the OP comment
thpool_add_work expects a function with void* argument for a reason. In such a way, you can pass any kind of parameter into the thread function, albeit in a type-unsafe way.
You pass the address of the parameter converted to void* as the 3rd argument of thpool_add_work. Afterwards, you cast a pointer to void back to the pointer to your expected parameter type and dereference it to get the value of the parameter. I gave the example for int a above, now how it would look for a float:
void* test3(void* a)
{
float fa = *(float*)a;
.....
return NULL;
}

Try this
thpool_add_work(threadpool, (void* (*)(void*))task2, (void*)a);
C converts void* to any type automatically, C++ does not.
You could improve the code with a typedef
typedef void* (*worker_func_t)(void*);
thpool_add_work(threadpool, (worker_func_t)task2, (void*)a);
int thpool_add_work(thpool_t* tp_p, worker_func_t function_p, void* arg_p)
{
// some code here
}

Related

error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

Getting error:
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
on g++
on the following code:
void* func(void *s)
{
int i = 0;
int self = (int *)s;
printf("Thread Entered: %d\n", self);
sm.lock(self);
// Critical section (Only one thread
// can enter here at a time)
for (i=0; i<MAX; i++)
ans++;
sm.unlock(self);
}
You need to change int self = (int *)s; to int self = *((int *)s); or to int * self = (int *)s;.
You need to think of these as two different things. One is a pointer to memory where the value is stored (int*) and the other is an actual value (int).
Looking at your function declaration void* func(void *s), your s parameter is of type void, this will need to be int if you wish to convert it.
Your data types seem a bit mixed, which just doesn't fly do well in C/C++. Can you clean it? If you are using this function with pthread_create(), as per the documentation with example for this function, try..
// your pthread_create call..
int SOME_INT = 123;
s = pthread_create(&thread_id, &attr, &thread_start, &SOME_INT);
//...and your function
void* func(void *s)
{
int self = (int*) s;
Pointers can be confusing. See if that above code looks similar, in particular to passing the last parameter for pthread_create as a pointer reference. And then try your original code. It might just be that it wasn't passed as a reference.
See what that yields you, else try storing it as a pointer and then converting on use.
void* func(void *s)
{
int *self = s;
sm.lock(*self); // but can give a potential race condition.
In the second line of the function body, I suspect you were trying obtain the value at s (as an int pointer), but you actually cast it directly to an int. That would yield the address in s rather than the value stored there.

Cannot seem to cast void* to struct in c++

I have a very simple method with the following prototype:
void *station_0(void* p1);
I am calling it like this:
product_record r;
pthread_create(thread, NULL, station_0, (void *)&r);
Inside this method all I need to do is cast p1 to an already defined struct product_record, I am currently trying this inside of my method:
product_record p = (product_record)p1
but the compiler complains on that line(above) saying error: invalid conversion from 'void*' to 'int' [-fpermissive]
I don't think I understand this warning at all. Why cannot I simply cast a void* to my struct?
You need two steps - convert the void pointer to a product_record pointer and then de-reference that. This can be done in the line
product_record p = *(static_cast<product_record *>(p1));

Why can a const value not be changed in C++ but in C? [duplicate]

This question already has answers here:
how to avoid changing value of const in C
(4 answers)
Closed 8 years ago.
In an interview, I was asked to change constant value in CPP, but I said in CPP it is not possible but in c it is possible using pointer.
Interviewer said that using CPP it is possible and asked me to try but I couldn't and I came back to my room and tried again but what I figured out that I was able to change in C but same code was getting error when compiled as C++.
#include<stdio.h>
main()
{
const int i=5;
int *p;
p=&i;
*p=8;
printf("%d",i);
}
This code is changing the constant value of i in c but when I compile in CPP then
I get an error:
invalid conversion from 'const int*' to 'int*'
Given your error, the actual program must have been the following:
#include<stdio.h>
main()
{
const int i=5;
int *p;
p=&i;
*p=8;
printf("%d",i);
}
This produces a warning with gcc:
warning: assignment discards 'const' qualifier from pointer target type
and an error with g++:
error: invalid conversion from 'const int*' to 'int*'
So, let's change the title of your question to a better one:
Why does C allow conversion from const int * to int *, but C++ doesn't?
The reason why one gives a warning and another gives an error is not because one allows you to discard const qualifier and the other doesn't. It's merely because the C standard leaves such incorrect actions as undefined behavior, while the C++ standard specifically marks it as an error. Either way, doing this is wrong.
You can read this similar question asking why this is possible in C.
What I think interviewer wanted this:
int n = 0;
int const *p = &n;
The expression &n has type “pointer to int.” The declaration for p converts &n to type “pointer to const int,” adding a const qualifier in the process. This is a valid qualification conversion. This conversion in no way invalidates n’s declaration. The program can still use n to alter the int object, even if it can’t use *p for the
same purpose.
*p = 5; // wrong
But
n = 5; // OK
now *p is 5 although it is const type!
Now try to run this code in GCC or g++, it will work:
#include<stdio.h>
int main()
{
int n = 0;
const int *p;
p=&n;
printf("%d\n",*p);
n = 5;
printf("%d\n",*p);
return 0;
}
EDIT: The only way to change the value of const qualified object in C and C++ both is, change the value in the initialization statement:
const int i = 5 ---> const int i = 8
This is why const_cast exists, I believe the interviewer asked this because they have to deal with poorly designed library code they have no control over, however normally you shouldn't have to resort to using it in production.

Cast integer array to void pointer - pthread_create

for passing arguments, pthread requires void pointer. I want to pass two variables, int and long. To save myself some trouble, I will pass two long instead. So this is what I do:
int main(int argc, char *argv[])
{
/*SOCKET INIT*/
pthread_t socketTh;
long data[2] = {ip2l(IP),80};
pthread_create(&socketTh, 0, &serverConnect, (void*)data); //ERROR HERE
while(true) {
/*event loop*/
}
quit_thread(&sockerTh); //just an EXAMPLE! I don't know how to quit threads, I will google it later
return 0;
}
Error:
error: invalid conversion from 'void (*)(void*)' to 'void* (*)(void*)'
But it seems that this is not the correct way to retype long pointer to void pointer. I wonder not of threads Stackoverflow has suggested me didn't help, as well as any Google search. So maybe, try to explain it really slowly, because I'm beginner and I'm still lost in data types.
Thank you.
Update:
I create the unsigned long* in main(). This means this variable will last as long as the program itself.
The error message refers to the third argument. pthread_create wants a pointer to a function that takes a void* and returns void*. Apparently the function serverConnect is a function that takes a void* and returns void.

error in clone system call sentence in c++

I am trying to to run c code in c++ which uses clone inside , I got an error which I couldn't solve it , anyone used clone in c++ before , and can help .
my code:
int variable, fd;
using namespace std ;
int do_something() {
variable = 42;cout << "sana" << endl ;
close(fd);
_exit(0);
}
int main() {
void **child_stack;
char tempch;
variable = 9;
fd = open("test.file", O_RDONLY);
child_stack = (void **) malloc(16384);
printf("The variable was %d\n", variable);
clone(do_something, child_stack,CLONE_VM|CLONE_FILES, NULL);
sleep(1);
printf("The variable is now %d\n", variable);
if (read(fd, &tempch, 1) < 1) {
perror("File Read Error");
exit(1);
}
printf("We could read from the file\n");
return 0;
}
and i got the errors:
dell#ubuntu:~$ g++ n.cpp -o n
n.cpp: In function ‘int main()’:
n.cpp:40:62: error: invalid conversion from ‘int ()()’ to ‘int ()(void*)’ [-fpermissive]
/usr/include/x86_64-linux-gnu/bits/sched.h:83:12: error: initializing argument 1 of ‘int clone(int ()(void), void*, int, void*, ...)’ [-fpermissive]
dell#ubuntu:~$
Compiler is telling you that first argument to clone is supposed to be int(*)(void*) (a pointer to function taking one void* parameter and returning int) and that you're trying to pass it int(*)() (a pointer to function taking no parameters and returning int).
The former can't be implicitly converted to the latter, hence the error.
To fix it, you can define do_something as:
int do_something(void*)
{
// your code
}
You really should not use the clone(2) system call. It is (sort of) reserved -like futex(2)- to the implementation of pthreads. And C++11 standard practically requires that pthreads are linked into the compiled application.
If you want to use clone (which is a probable mistake), retrict yourself to C, and carefully avoid the pthread library to be needed, even indirectly; by your application.
If you insist on using clone, the child_stack argument to it should be suitably aligned (at least to a page of 4Kbytes), and malloc does not guarantee that. You might use mmap or posix_memalign.
But really, don't use clone (specially not from C++). Use pthreads.