Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


C++ Void* Questions


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
20 replies to this topic

#1 bennettbugs   Members   -  Reputation: 493

Like
0Likes
Like

Posted 07 March 2012 - 09:57 PM

I was wondering... i know a void* turns a variable into raw binary data. is it possible to have a void* be a pointer to another variable?


also, how would i store the address of the variables as a pointer?

int *p=0;//obviously

then store the address of p, so

a= point to p;

a=1;

//p is now 1

Sponsor:

#2 Vlad86   Members   -  Reputation: 130

Like
1Likes
Like

Posted 07 March 2012 - 10:51 PM

void pointer simply means that an undefined type.
You can typecast it in whatever you like. (also all other types)

Example:
int* pixelArray = (int*)voidPtr;
Usually its a bad practice.. you must always think what your data is and what you do with it. But in some cases it can be unavoidable.

Pointer is an address.
So if you have a pointer of A, it means that the pointer contains the memory address where A is stored.

#3 bennettbugs   Members   -  Reputation: 493

Like
0Likes
Like

Posted 07 March 2012 - 11:02 PM

i see. why is it bad practice? im on the verge of using it where i need different types for the same variable, which is alot.
so this works?

bool a=true;

void foo(void* val)
{
//found its a bool
bool* nVal=(bool*)val;
if(nval==true){nval=false;}
}

foo((void*)&a);

#4 Cornstalks   Crossbones+   -  Reputation: 6995

Like
1Likes
Like

Posted 07 March 2012 - 11:11 PM

It works, yeah, but the real problem isn't the fact that you're using a void*. The real problem is that you need to do it a lot. That signals a design flaw in your program.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#5 Vlad86   Members   -  Reputation: 130

Like
0Likes
Like

Posted 07 March 2012 - 11:13 PM

one of the examples if you try to delete void pointer that points to a class it wont call the destructor of that class.
It also means that you have questionable architecture.

Can you tell me why do you want to use it and for what?

#6 bennettbugs   Members   -  Reputation: 493

Like
0Likes
Like

Posted 07 March 2012 - 11:16 PM

XD im writing some code for a menu button, which has to either point to a bool, int, float or string/char array somewhere in the program. it would be alot easier to have it point to a variable and tell it the class than to make seperate buttons for each variable.

#7 Vlad86   Members   -  Reputation: 130

Like
0Likes
Like

Posted 07 March 2012 - 11:19 PM

Its cleaner to use inheritance in this case.
Button that is derived specific per type.

#8 bennettbugs   Members   -  Reputation: 493

Like
0Likes
Like

Posted 07 March 2012 - 11:22 PM

:-\ i read the book i learned c++ from (1200 pages) and i guess i forgot about some stuff.. time to hit the books. :P

#9 Washu   Senior Moderators   -  Reputation: 6412

Like
1Likes
Like

Posted 08 March 2012 - 12:42 AM

Alternatively you can use a discriminate union, such as boost::variant. You can see a sample of using boost::variant here

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#10 SimonForsman   Crossbones+   -  Reputation: 6518

Like
1Likes
Like

Posted 08 March 2012 - 01:36 AM

Its cleaner to use inheritance in this case.
Button that is derived specific per type.


I'd probably use templates or a union if i need a class dealing with multiple parameter types. in C++ a discriminated union such as boost::variant is prefered over a normal C style union due to the added type safety, C unions however work well enough if you do something similar to the SDL_Event union, (a union of a 1 byte type identifier and a set of structs where the structs all start with a 1 byte type identifier aswell).

For a GUI a signals/slots, event or callback mechanism would be preferable to having buttons with pointers to data owned by other parts of the program.
I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#11 Tribad   Members   -  Reputation: 931

Like
1Likes
Like

Posted 08 March 2012 - 01:51 AM

if(nval==true){nval=false;}

I think this is not what you intended to do. You compare the pointer nval with true not the value nval points to.
Comparing any pointer with a boolean in C++ is legal. Its an artifact from C where

if (ptr) do something

compares the pointer against NULL. This is how pointer checking is done in a short form in C.
For C++ the pointer is converted to a boolean and afterwards compared.

You will not get a warning about that.
It shows a bit why type safe programming is a good thing and why void pointers should be avoided.

#12 Rattenhirn   Crossbones+   -  Reputation: 1903

Like
0Likes
Like

Posted 08 March 2012 - 04:47 AM

i see. why is it bad practice? im on the verge of using it where i need different types for the same variable, which is alot.
so this works?

bool a=true;

void foo(void* val)
{
//found its a bool
bool* nVal=(bool*)val;
if(nval==true){nval=false;}
}

foo((void*)&a);


It's bad practice, because you're working around the type system of C and C++, so the compiler won't be able to check anything for you.

As others have pointed out, "union" can be used to treat one memory location as more than one type, but in this case, I'm sure there are even better ways using OO or templates.

One more thing: If you're using C++, also use C++ casts. In this case this one would be the correct one: bool* nVal=reinterpret_cast<bool*>(val);
This would make it clear to everyone what you're doing.

#13 e‍dd   Members   -  Reputation: 2105

Like
3Likes
Like

Posted 08 March 2012 - 01:28 PM

One more thing: If you're using C++, also use C++ casts. In this case this one would be the correct one: bool* nVal=reinterpret_cast<bool*>(val);

You could use static_cast, in fact. The C++0x draft standard even defines reinterpret_casts between pointer types as if static_cast-ing through a void* intermediary (5.2.10.7).

#14 Kyall   Members   -  Reputation: 287

Like
1Likes
Like

Posted 08 March 2012 - 09:27 PM

I'm going to be pro union here. But I also strongly recommend against not using strong data types, have a look at templated functions or something first. But if no other option, use a union. From reading your description though, maybe try a template like:

template <typename T>  class MenuButton
{
public:
  MenuButton( T* a_dataMember );
protected:
  T* _dataMbr;
};

This allows you to have a separate class for each type, without actually writing all the code to do that. Use it like:

float val1 = 3.14f;
MenuButton<float> fButton = MenuButton<float>(&val1);
char* val2 = "SomeString";
MenuButton<char> strButton = MenuButton<str>(&val2);

And if you need to access these different types using one type, so if you're putting these types in a list, use inheritance like so:

class MenuItemBase
{
// Stuff, abstract functions so you can actually use the child classes 
};
template <typename T> class MenuButton : public MenuItemBase
{
  // etc as above, except with some implementations of the abstract functions to allow you to use the class effectively 
};

But keep in mind, that any functions you declare for a templated class, must be defined before they are used. So you will have to do this:

// In the header file:
class MenuItemBase
{
public: 
     virtual void MyFunc(int&) = 0; 
};
template <typename T> class MenuButton : public MenuItemBase
{
public:
  virtual void MyFunc( int& x ) { x = 5; }  
};
// Or this, also in the header file

class MenuItemBase
{
public: 
     virtual void MyFunc(int&) = 0; 
};
template <typename T> class MenuButton : public MenuItemBase
{
public:
  virtual void MyFunc( int& x );
};
template <typename T> void MenuButton<T>::MyFunc(int& x)
{
  x = 5;
}
// Instead of more normal header class declaration then cpp class definition

I'm sorry that that's the way you'll have to define a template class, but take it up with those pricks on the c++ standards board who decided to make the export keyword a blank reserved keyword than to have to do any work whatsoever on their compilers to keep themselves compliant.
I say Code! You say Build! Code! Build! Code! Build! Can I get a woop-woop? Woop! Woop!

#15 samoth   Crossbones+   -  Reputation: 5319

Like
1Likes
Like

Posted 09 March 2012 - 03:14 AM

From a design point of view, why does a button need to point to "some memory location" that it modifies at all? What would it be supposed to do with the void* anyway, if it doesn't know what it points to and what it is used for? It can neither do a meaningful operation on the value, nor do any meaningful consistency checks.

A button in its basic form sends a single event in reaction to the user doing a single thing. It doesn't know and should not know what value might be changed somewhere else. A more advanced button will maybe send additional events for mouse over and whatnot... but it still does not know about anything outside its little box.

Some other piece of the application receives the generated event (via a callback or a message queue, or a socket, or whatever mechanism you like... a pigeon if you want), and that piece of code reacts to the event. It knows what value is to be changed in response (if there is one), and it knows its type.

#16 Red Ant   Members   -  Reputation: 463

Like
1Likes
Like

Posted 09 March 2012 - 05:02 AM

I'm sorry that that's the way you'll have to define a template class, but take it up with those pricks on the c++ standards board who decided to make the export keyword a blank reserved keyword than to have to do any work whatsoever on their compilers to keep themselves compliant.


Well, if you want to keep the implementation separate from the interface you could still do it like this:

// in MenuButton.h
#ifndef MenuButton_h
#define MenuButton_h

class MenuItemBase
{
public:
	virtual void MyFunc(int&) = 0;
};

template <typename T> class MenuButton : public MenuItemBase
{
public:
	virtual void MyFunc( int& x );
};

#include "MenuButton.hpp"

#endif


// in MenuButton.hpp
template <typename T> void MenuButton<T>::MyFunc(int& x)
{
  x = 5;
}


#17 bennettbugs   Members   -  Reputation: 493

Like
0Likes
Like

Posted 10 March 2012 - 12:14 AM

Well, im pretty good with not leaving behind errors, and i have gotten it to work perfectly. i like all the ideas, but a void* pointer would be the easiest solution. although some may say its bad practice, it only is if you dont use it right. thanks for the ideas. :P

#18 mrbastard   Members   -  Reputation: 1573

Like
0Likes
Like

Posted 10 March 2012 - 12:35 PM

Easiest now, sure. But I'd argue that's only because you don't fully understand the other options. Type-safety is a very very valuable thing, and throwing it away shouldn't be taken lightly. That said, this is perhaps one of those things where you can't understand why it's so important until it affects you personally - when it bites you in a few years time, you'll understand Posted Image So it may be more valuable to you to make the mistake now so you can learn from it later. Or you may be absolutely right - you know your situation better than we do!

Anyway, I have another suggestion to add to the (very good) advice above. I think I'd go with each button holding an std::function<void(void)>, and use lambda capture to automagically get references to the needed variables. This is because I suspect that you don't actually want to say to a button "here, set this variable when you're clicked" - it would be far more useful to you to be able to say to a button "here's an arbitrary bit of code - run it when you get clicked".

#include <functional>
#include <assert.h>
struct MyButton
{
	void SetOnClickHandler(std::function<void(void)> handler)
	{
		onClickHandler = handler;
	}
	void OnClick()
	{
		if( onClickHandler )
		{
			onClickHandler();
		}
	}
	std::function<void (void)> onClickHandler;
};
struct SomeGameLogicClassOrOther
{
	void setupButton(MyButton& button)
	{
		auto myFunc = [&]()
		{
			//note m_buttonHasBeenClicked has been captured by reference
			//=> you could capture other stuff by reference here too
			//or just call a method on the SomeGameLogicClassOrOther
			//which would allow you to do some checks or more complex logic
			// - as Samoth pointed out would be useful
			m_buttonHasBeenClicked = true;
		};
		button.SetOnClickHandler( myFunc );
	}
	bool m_buttonHasBeenClicked;
};
int main(int argc, char* argv[])
{
	SomeGameLogicClassOrOther logic;
	MyButton button;
	logic.setupButton(button);
  
	button.OnClick();
	assert(logic.m_buttonHasBeenClicked);
	return 0;
}

std::function and lambda are really nice tools for doing this sort of thing in a generic yet type-safe way.

Edit: unless you don't need to change the behaviour of a button instance at run time, in which case I'd go for the template option. Posted Image


#19 kunos   Crossbones+   -  Reputation: 2224

Like
1Likes
Like

Posted 11 March 2012 - 03:15 AM

Well, im pretty good with not leaving behind errors, and i have gotten it to work perfectly. i like all the ideas, but a void* pointer would be the easiest solution. although some may say its bad practice, it only is if you dont use it right. thanks for the ideas. Posted Image


sadly you just missed a chance to learn something that will make you a better programmer in the long run and the entire point of C++.
If this is a paid gig then fine, you got it working and you'll get paid. If this is something you do to learn, you did just learn the wrong thing.

Stoustrup.. the author of C++ calls "dangerous" programmers with obsolete programming practices "void* guys" .. you do the math ;)

#20 Kyall   Members   -  Reputation: 287

Like
0Likes
Like

Posted 11 March 2012 - 10:14 AM

Man, I can be so much more dangerous than a void* guy. But I won't act so dangerously for production code. Trying to debug something, then it's okay just cause it minimises the amount of code you need to write to work out wtf is up with a system.

Funnily enough void* and other dangerous sorts of programming are pretty much what leads to the types of errors I've found in the past that I had to do dangerous programming to debug...
I say Code! You say Build! Code! Build! Code! Build! Can I get a woop-woop? Woop! Woop!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS