I have some problems with referencing void pointer to class.
I created a node "index" with a void data pointer which point to a class "studentinfo";
however, I encountered problems when I was trying to extract data member of the class "studentinfo".
The output error message is saying:
"invalid type argument of unary '*' (have 'int')
int main()
{
...
Studentinfo *stu=new Studentinfo(id,name,score);
index=createNode(stu);
cout<<*static_cast <Studentinfo*> (index->dataPtr)->id; //Error ocurrs
...
}
-> already does a deference. So stu->id is the same as (*stu).id.
In your code you are actually trying to deference id, which is an int. This is why you get that error.
The -> operator dereferences a pointer and accesses it's member. The * also does this. Because you've included both, you're actually trying to do it twice.
Probably the correction to the code you're looking for probably just needs to remove the extra * dereference. The error you're getting is because static_cast <Studentinfo*> (index->dataPtr)->id is already fully dereferenced and returning what you want, id. id is an int, so the * dereference operator is attempting to dereference an id(an int) which gives the error invalid type argument of unary '*' (have 'int')
Now... with all that said I'm going to reiterate some of what your commentors have already said. This is extremely unsafe code. There's rarely a good reason to use void pointers or malloc in C++. Try to spend some more time learning about A: Constructors, B: How they interact with the new operator, and C: templates.
You will get code that is more readable and less error prone utilizing these techniques. Your main will be much more readable, as the statement that is currently giving you trouble can be simplified to cout<<index->dataPrt->id if your node uses templates, rather than a void pointer.
Related
I am getting a weird syntax error when trying to reinterpret-cast a pointer:
void my_function(std::unique_ptr<float[]> ptr) {
// Some stuff
... = reinterpret_cast<uint8_t[]*>(ptr.release());
// Some other stuff
}
I'm getting the following error message:
error: expected '>'
reinterpret_cast<uint8_t[] *>(ptr.release()));
^
I have a '<' and a matching '>', so I don't understand what's causing the error. What could be the problem here?
Assuming you're either trying to serialize data, you should be casting to a regular uint8_t pointer. For this, just do:
reinterpret_cast<uint8_t*>(ptr.release());
Note that ptr.release() releases onwership of the pointer owned by the unique_ptr, and that deleting a pointer to an array of float as a pointer to an array of uint8_t is undefined behavior. Always delete a pointer as it's original type, without casting it.
I would recommend using ptr.get() instead, as this doesn't transfer ownership:
reinterpret_cast<uint8_t*>(ptr.get());
Why you got the error: The syntax for a pointer to an array is uint8_t(*)[]. It's... weird, and until another commenter pointed it out, I didn't know that it existed (it's an artifact of backwards compatibility with C).
Because of that, the compiler doesn't expect to see a * after uint8_t[], so it says that it expected the closing bracket of the reinterpret_cast.
Do you really want a pointer to an array of uint8_t, as opposed to just a pointer to uint8_t ?
If so, it is written uint8_t(*)[].
But I think what you actually want is most likely a pointer to uint8_t, i.e. uint8_t *.
First of all, thank you to whoever is reading and to whom you can respond.
This part of code, is part of an interface library gui, totally written in c.
But I'm tempted to compile these written files in c, with a c ++ compiler to be able to integrate into a program I'm doing with wxwidgets.
Within the c files, I have several function calls that have as arguments, pointers to other functions.
typedef struct {
void (*fchd_ptr)(bool);
uint16_t xpos;
uint16_t ypos;
...
...
}BUTTON_t;
void BT_SetHandler(BUTTON_t* ptr, void* fchd_ptr)
{
if (ptr == NULL)
return;
ptr->fchd_ptr = fchd_ptr; // OK in C, ERROR In C++
}
When I try to compile in C ++, I get this error.
ptr-> fkt_ptr = fkt_ptr;
// error: invalid conversion from 'void *' to 'void (*) (bool)' [-fpermissive]
If I cast an explicit cast.
ptr-> fkt_ptr = (bool *) fkt_ptr;
// error: can not convert 'bool *' to 'void (*) (bool)' in assignment
Any help, and explanation how to solve it will be welcome.
Your explicit cast is wrong. You cast to bool * (pointer to object of type bool), when you really should be casting to void (*)(bool) (pointer to function taking a bool and returning nothing).1
If you replace that line by
ptr->fchd_ptr = (void (*)(bool)) fchd_ptr;
it will compile in both C and C++.
If possible, however, you should try to compile your C code in C only - while we might get this one thing working, the two languages are not always fully compatible, and you may well run into trouble down the road. Generally, it is possible to compile C code separately from the C++ parts. If you use extern "C" in your header files, you can simply link the C++ objects and the C objects together, or keep the C part in a separate library (static or dynamic).
Additionally, I would recommend reworking the C API so that it really takes a function pointer all the way through if that is at all possible. Aliasing through void * is ugly and can lead to some really nasty bugs and crashes if you pass in the wrong pointer type.
1 Function pointers are generally very different from object pointers, and it is implementation-defined whether you are even allowed to cast between the two. Here, you want a pointer to a function, not a pointer to an object (like bool* would be a pointer to an object of type bool) so that you can call it later. You can see in your code sample that void (*fchd_ptr)(bool) is the declaration of the variable that you assign to, which makes void (*)(bool) its type. If you find the notation somewhat confusing, cdecl.org is a great way to deal with those convoluted array, pointer and function pointer names that come from C.
If you change the signature of the function to accept a function pointer that matches the type expected by ptr->fchd_ptr. Then, you would not need to use a cast to complete the assignment.
Based on your question, this would be:
void BT_SetHandler(BUTTON_t* ptr, void (*fchd_ptr)(bool))
However, if you are not sure what the type is for ptr->fchd_ptr, you can make the compiler figure it out for you. Previously, this could only be done with a template function and it would derive a type based on what was passed into the function call at compile time. However, C++.11 provdes decltype, which allows you to enforce the type you want for the function parameter, rather than letting the compiler deduce one from callers of the function.
void BT_SetHandler(BUTTON_t* ptr, decltype(ptr->fchd_ptr) fchd_ptr)
This is fine so long as you are intent on compiling your code with a C++ compiler.
Consider following program:
#include <iostream>
void f(void* a)
{
std::cout<<"(void*)fun is called\n";
std::cout<<*(int*)a<<'\n';
}
int main()
{
int a=9;
void* b=(int*)&a;
f(b);
return 0;
}
If I change the function call statement like this:
f(&b);
It still compiles fine & crashes at runtime. Why? What is the reason? Should I not get the compile time error? Because the correct way to call the function is f(b). right? Also, why it is allowed to pass NULL to a function whose parameter is of type (void*)?
Please correct me If I am missing something or understanding something incorrectly.
It still compiles fine & crashes at runtime. Why? What is the reason?
Because void* is a technique for removing all type-safety and type checking.
Should I not get the compile time error?
By using void* instead of the correct pointer type int*, you are expressly telling the compiler not to tell you if you are using a type incorrectly or in an undefined way.
Because the correct way to call the function is f(b). right?
That's where your function declaration and contents disagree.
std::cout<<"(void*)fun is called\n";
std::cout<<*(int*)a<<'\n';
The contents above imply that a pointer to int should be passed:
void f(void* a)
This declaration implies some pointer should be passed, and no other restrictions are made.
void* can capture any type of pointers, there is no exception to void**
Ok.
As requested.
Do not use void pointers unless it you cannot think of any other way around it.
And the go to bed and think again.
Void pointers enables the programmer to forget about types. This means that the compile can give up on simple checks. This also in my mind means that the programmer has lost the plot.
Downvote me if you wish.
Using types have the luxury that the compiler can check things out for you. E.g. how things are related. How to treat that object.
But using a void pointer you are very much on your own. Good luck
You'll not get a compile time error because f(&b) calls f and passes the address of b as a parameter which is then casted into a void*. You get a runtime error because then, you are trying to cast a pointer to an integer as an integer.
But yes, as others have stated, doing this a very bad.
First
You can have a void* point to void**. Your code is one of the many examples showing how dangerous void* pointers can be.
Second
You should for type conversion use:
void* b = static_cast<int*>(&a);
instead of the c style conversion you are using:
void*b = (int*)&a;
If I change the function call statement like this:
f(&b);
It still compiles fine & crashes at runtime. Why?
Your function f(void*) will accept a pointer to any type, without complaint. Any pointer quietly converts to a void pointer. A pointer to a pointer is still a pointer. So your second case does indeed compile just fine. And then it crashes. Maybe.
In the first case, you converted from a pointer to int to a pointer to void back to a pointer to int. Those round trip conversions through void* (and also through char*) must work. In the second case, you converted from a void** to a void* to an int*. Now you're invoking undefined behavior. Anything goes. On my computer, my compiler, your code runs just fine. It prints garbage. I was quite sure that your code wouldn't erase my hard drive, but it could. Anything goes with undefined behavior. Don't invoke undefined behavior.
The reason for supporting void* is historic. There is a lot of old C and C++ code that use void pointers. The only reason to write new C++ code that uses void pointers is if you need to interact with one of those old functions that use void pointers.
I found myself here because I am working on a homework assignment that requests the same functionality. After combining each comment, this is what I came up with.
// A function that accepts a void pointer
void f(void* a)
{
std::cout<<"(void*)fun is called\n";
std::cout<< "value for a: " << *(int*)a << '\n';
}
int main() {
int a = 9;
void* c = static_cast<int*>(&a);
int b = 3;
f(&b);
f(c);
}
This is a follow up question to my previous post: C++: Initializing Struct and Setting Function Pointer
My new question is how do I call a pointer-to-member function within a struct? I have modified my previous code to:
float MyClass::tester(float v){
return 2.0f*v;
}
struct MyClass::Example{
float(Scene_7::*MyFunc)(float);
float DoSomething(float a){
return (MyFunc)(a); //ERROR, SEE BELOW FOR OUTPUT
}
};
I then set the function as follows, and output the result to the call:
struct Example e;
e.MyFunc = &MyClass::tester;
std::cerr << e.DoSomething(1.0f) << std::endl;
I get the following error: must use '.' or '->' to call pointer-to-member function...
The problem is I don't know how to do this. I am guessing I have to call something like this->*(myFunc)(a) within DoSomething but this references the struct. I have tried searching "this within struct pointer-to-member function" but have not been able to find anything. Any help or suggestions would be great. I feel like I am close but it is just a matter of syntax at this point.
The operator precedence of .* and ->* is, IMHO, broken. You need to wrap the operands in parentheses in order to call.
return (this->*MyFunc)(a);
Otherwise, the compiler thinks you're doing this->*(MyFunc(a)), which is obviously invalid.
Interestingly enough, (this->*MyFunc) as a standalone expression is also invalid. It needs to be called on the spot.
I cant tell if you have other errors, do to the lack of code, but you are calling a member function the wrong way, you call them like this:
return (obj->*MyFunc)(6);
I am not sure if you can use this in place of obj on the line above, since from the declaration, you need a pointer to an object of type Scene_7, so you will need to know a pointer of the correct type at that spot in the code..
Remember that . operator has higher precedence than the * operator. So when dealing with pointes and structs etc you will need to use paranthesis or -> operator which means that the pointer points to what.
Is this correct?
int (*(*ptr)())[];
I know this is trivial, but I was looking at an old test about these kind of constructs, and this particular combination wasn't on the test and it's really driving me crazy; I just have to make sure. Is there a clear and solid understandable rule to these kind of declarations?
(ie: pointer to... array of.. pointers to... functions that.... etc etc)
Thanks!
R
The right-left rule makes it easy.
int (*(*ptr)())[];can be interpreted as
Start from the variable name ------------------------------- ptr
Nothing to right but ) so go left to find * -------------- is a pointer
Jump out of parentheses and encounter () ----------- to a function that takes no arguments(in case of C unspecified number of arguments)
Go left, find * ------------------------------------------------ and returns a pointer
Jump put of parentheses, go right and hit [] ---------- to an array of
Go left again, find int ------------------------------------- ints.
In almost all situations where you want to return a pointer to an array the simplest thing to do is to return a pointer to the first element of the array. This pointer can be used in the same contexts as an array name an provides no more or less indirection than returning a pointer of type "pointer to array", indeed it will hold the same pointer value.
If you follow this you want a pointer to a function returning a pointer to an int. You can build this up (construction of declarations is easier than parsing).
Pointer to int:
int *A;
Function returning pointer to int:
int *fn();
pointer to function returning a pointer to int:
int *(*pfn)();
If you really want to return a pointer to a function returning a pointer to an array of int you can follow the same process.
Array of int:
int A[];
Pointer to array of int:
int (*p)[];
Function returning pointer ... :
int (*fn())[];
Pointer to fn ... :
int (*(*pfn)())[];
which is what you have.
You don't. Just split it up into two typedefs: one for pointer to int array, and one for pointer to functions. Something like:
typedef int (*IntArrayPtr_t)[];
typedef IntArrayPtr_t (*GetIntArrayFuncPtr_t)(void);
This is not only more readable, it also makes it easier to declare/define the functions that you are going to assign the variable:
IntArrayPtr_t GetColumnSums(void)
{ .... }
Of course this assumes this was a real-world situation, and not an interview question or homework. I would still argue this is a better solution for those cases, but that's only me. :)
If you feel like cheating:
typedef int(*PtrToArray)[5];
PtrToArray function();
int i = function;
Compiling that on gcc yields: invalid conversion from 'int (*(*)())[5]' to 'int'. The first bit is the type you're looking for.
Of course, once you have your PtrToArray typedef, the whole exercise becomes rather more trivial, but sometimes this comes in handy if you already have the function name and you just need to stick it somewhere. And, for whatever reason, you can't rely on template trickery to hide the gory details from you.
If your compiler supports it, you can also do this:
typedef int(*PtrToArray)[5];
PtrToArray function();
template<typename T> void print(T) {
cout << __PRETTY_FUNCTION__ << endl;
}
print(function);
Which, on my computer box, produces void function(T) [with T = int (* (*)())[5]]
Being able to read the types is pretty useful, since understanding compiler errors is often dependent on your ability to figure out what all those parenthesis mean. But making them yourself is less useful, IMO.
Here's my solution...
int** (*func)();
Functor returning an array of int*'s. It isn't as complicated as your solution.
Using cdecl you get the following
cdecl> declare a as pointer to function returning pointer to array of int;
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension'
(maybe you mean "pointer to object")
int (*(*a)())[]
This question from C-faq is similar but provides 3 approaches to solve the problem.