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.
Related
I found out that using a C compiler the code below works but not with a C++ compiler. I understand that casting to void** is the correct usage but I can't understand why it compiles with the C compiler even if I use the void* (commented out).
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
Can someone explain why this is the case?
In C there is allowed to assign a pointer of the type void * to a pointer of other type. This takes place in this call
fn((void *)&pvalue)
where the argument has the type void * that is assigned to the function parameter that has the type void **.
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
However such an assignment in general is unsafe. For example the value of a pointer of the type void * can not be properly aligned to be assigned to a pointer of other type.
So it was decided to not allow such an assignment in C++ to make programs more safer.
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
It compiles because void* is implicitly convertible to other pointers in C.
fn((void **)&pvalue); // correct, works for both C/C++
This may be well-formed because of the cast, the standard doesn't technically give explicit guarantee that conversion to void** and back yields the same address.
While this may be likely to work in practice, there is no reason to not use void* as the function argument instead, which does have the guarantee. As a bonus, you won't need the cast in the call. Like this:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
Of course, this is assuming type erasure is needed in the first place. Avoid void* when it is not needed.
For avoidance of doubt, there is nothing correct in
fn((void **)&pvalue);
It is just as incorrect as
fn((void *)&pvalue);
The correct way to use the API is to do
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
or
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
with
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
You're not allowed to access an object using any other pointer type, other than the declared type, compatible type, or a character type. Furthermore, while void * is used as a generic pointer type to all sorts of objects in C, there is no generic pointer to a pointer type in C - other than void *!
And this is the reason why the void ** is almost always a sign of a design error in APIs - most usages are just wrong.
I'm trying to understand pointer return types from functions.
The following example produces a type conversion error.
#include <iostream>
using namespace std;
int* abc(int* y)
{
int x=y;
int *z = &x;
x++;
return z;
}
int main()
{
int *a = abc(100);
int b = *a;
cout << a <<endl;
cout << b <<endl;
return 0;
}
The error message is:-
In function 'int* abc(int*)': 6:11: error: invalid conversion from 'int*' to 'int' [-fpermissive]
In function 'int main()': 14:19: error: invalid conversion from 'int' to 'int*' [-fpermissive]
4:6: note: initializing argument 1 of 'int* abc(int*)'
How to resolve the above error and also what is the difference between the following function forms and their appropriate calling syntax,
int* function()
int * function()
int *function()
The argument type in
int* abc(int* y)
is int*. When you call the function,
int *a = abc(100);
you are passing 100, an int. It is not a pointer to an int.
You can fix the problem by using:
Option 1
Change the argument type.
int* abc(int y) { ... }
Option 2
Change the way you call the function.
int x = 100;
int *a = abc(&x);
If you follow this option,
The line
int x=y;
needs to be modified. Type of y is int*, not int. You'll have to change the line to:
int x=*y;
Problem
You are returning the address of a local variable from the function. Dereferencing that address in the calling function is undefined behavior.
When you return an address from a function and the calling function dereferences that address, the address needs to be valid in the calling function. One way to do that is to allocate memory from heap using malloc.
int* abc(int* y)
{
int* x = malloc(sizeof(int));
*x = (*y + 1);
return x;
}
When you do that, you'll have to remember to call free in the calling function.
int x = 100;
int *a = abc(&x);
// Use a
// Deallocate memory
free(a);
The problem is not your return type. Your problem is on this line:
int x=y;
Here y is a pointer and you're trying to assign it to x which is an int.
You're also passing a literal 100 which is an int to the abc function which takes a pointer as an argument.
Finally, there is no difference between the types of the 3 functions you give. Whitespace is insignificant in this context.
Your first two statements in both functions are incorrect. 100 is not a pointer when main calls abc, and blindly assigning y to x won't work because the former is an int and the latter is an int pointer.
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.
This code
#include "alloca.h"
String str = "abc";
unsigned int *i;
void setup() {
Serial.begin(9600);
i = alloca(StringLength() * sizeof(i));
unsigned int j[StringLength() * sizeof(i)];
}
int StringLength() {
return str.length();
}
void loop() {
}
gives me the following error messages:
sketch_dec11f.cpp: In function ‘void setup()’:
sketch_dec11f.cpp:14:7: error: invalid conversion from ‘void*’ to ‘unsigned int*’
What am I doing wrong?
(tried it with malloc() as well, also didn't work!)
You definitely don't want alloca(). That's an allocation that is on the stack of the function and only lasts for the duration of the call. It lets you have dynamic arrays that go away on function return (in C++ you could do this with RAII, but in C alloca was the only way).
You just need a cast in your allocation. Try i = (unsigned int *)malloc(StringLength() * sizeof(*i)). Note the sizeof(*i). That's the size of one member: sizeof(i) is the size of the pointer and is not likely to be related to what's inside.
Malloc and alloca return void * pointers. Just change
i = alloca(StringLength() * sizeof(i));
to
i = (unsigned int *)alloca(StringLength() * sizeof(i));
I am not sure of alloca, but malloc return's void * and C++ unlike C doesn't support implicit conversion from void * to any other pointer type. This is one of the many areas where C++ differs from C.
Cast the returning pointer from alloca:
i = (unsigned int *) alloca(StringLength() * sizeof(i));
In C++, void pointers are not implicitly convertible to other pointers, unlike in C. Therefore you need a cast:
i = static_cast<unsigned int *>(alloca(StringLength() * sizeof(i)));
If I have a function that takes int *&, what does it means? How can I pass just an int or a pointer int to that function?
function(int *& mynumber);
Whenever I try to pass a pointer to that function it says:
error: no matching function for call to 'function(int *)'
note: candidate is 'function(int *&)'
It's a reference to a pointer to an int. This means the function in question can modify the pointer as well as the int itself.
You can just pass a pointer in, the one complication being that the pointer needs to be an l-value, not just an r-value, so for example
int myint;
function(&myint);
alone isn't sufficient and neither would 0/NULL be allowable, Where as:
int myint;
int *myintptr = &myint;
function(myintptr);
would be acceptable. When the function returns it's quite possible that myintptr would no longer point to what it was initially pointing to.
int *myintptr = NULL;
function(myintptr);
might also make sense if the function was expecting to allocate the memory when given a NULL pointer. Check the documentation provided with the function (or read the source!) to see how the pointer is expected to be used.
Simply: a reference to a pointer.
In C, without references, the traditional way to "relocate" a pointer, is to pass a pointer to a pointer:
void c_find(int** p, int val); /* *p will point to the node with value 'val' */
In C++, this can be expressed by the reference syntax, to avoid the awkward double dereference.
void cpp_find(int*& p, int val); // p will point to the node with value 'val'
It means a reference to a pointer to an int. In other words, the function can change the parameter to point to something else.
To pass a variable in, just pass an int*. As awoodland points out, what's passed in must be an l-value.
Edit:
To build on awoodland's example:
#include <iostream>
void foo(int*& var)
{
delete var;
var = new int;
}
int main(int argc, char* argv[])
{
int* var = NULL;
std::cout << var << std::endl;
foo(var); // this function can/will change the value of the pointer
std::cout << var << std::endl;
delete var;
return 0;
}
function takes a single parameter, mynumber which is a reference to a pointer to an int.
This is useful when you need to pass a pointer to a function, and that function might change the pointer. For example, if you function is implemented like this:
function(int*& mynumber)
{
if( !mynumber )
mynumber = new int;
*mynumber = 42;
}
...Then something like this might happen in the calling code:
int main()
{
int* mynumber = 0;
function(mynumber); // function will change what "mynumber" points to
cout << *mynumber;
return 0;
}
This is a reference to a pointer to int - you would have to pass in the address of an int to this function, and be aware that the function could change the pointer through the reference.
Dumb example:
void func(int*& iref)
{
iref = new int;
}
int main()
{
int i(0);
int* pi(&i);
func(pi);
// pi no longer equal to &i
return 0;
}