Sign in to follow this  

Messing with memory

This topic is 4375 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everyone. I'm just sitting here writing programs messing around with pointers, trying to get to know them better, and I decided to use the bit shift operator(>> or <<). I want to know why it's doing what it's doing. Here's my program.
#include <iostream>
using namespace std;
int main() {
  int a = 10;
  int* b = &a;
  cout<<a<<endl<<b<<endl;
  a>>=1;
  cout<<a<<endl<<b<<endl;
  return 0;
}

outputs: 10 0x22ff74 5 0x22ff74 and if I bitshift to the left instead of a 5, it gives 20. Shouldn't it change the memory allocation, not the variable?

Share this post


Link to post
Share on other sites
You are only bitshifting the value variable, so only the value is affected. You aren't touching the pointer. That's why the address outputted is still the same.

I'm not sure if the compiler would let you actually use the bitshift operator on the pointer.

Share this post


Link to post
Share on other sites
Hmmm... Okay. The only reason I'm doing this is because I don't understand the point of pointers. I have been programming in C++ forever and a half.. on and off, and all this time I haven't been able to find a good use for them.

Share this post


Link to post
Share on other sites
Like Endurion said you are only moving the bits in variable a.

Here are the bits in variable 'a' before the shift

... 01010

When added together they equal 10. (8+2=10)

Here they are after the shift.

... 00101

When added together they equal 5. (4+1=5)

Hope that explains bit shifting.

Share this post


Link to post
Share on other sites
The only line where you are bitshifting:

a>>=1;


Is being done directly on an integer variable, so it will shift the value.

I have no clue why anyone would want to shift a pointer, unless it was for some vodoo division or something.

Pointers are used "a lot" with graphics, and when dealing with classes or large amounts of data.

If you are learning c++, learning about pointers are a must.

Share this post


Link to post
Share on other sites
as i said, I've been learning C++ for 4 years now..(off and on) Back then I got discouraged because I couldn't understand it the slightest. I understand a lot more now, just can't find a use for pointers. I know how they work, I just can't find a use for them.

Share this post


Link to post
Share on other sites
Programming what? Have you ever not known how big an array needs to be? Guess you'd use a vector. Have you used virtual functions? Because without pointers they are useless.

I guess it's understandable really, everyone does their best to make pointers unnecessary, favouring containers and references etc. And when people do use them, they often use smart pointers.

Share this post


Link to post
Share on other sites
programming nothing really, just learning. I have had many failed attempts at making games, and other random things. I tried to make pong, tic tac toe, a console RPG, a length unit conversion calculator, a calculator, tetris, a graphical RPG, a side scroller. Aaah, it's so discouraging talking about my failing attempts at stuff.

Share this post


Link to post
Share on other sites
Quote:
Original post by Niddles
as i said, I've been learning C++ for 4 years now..(off and on) Back then I got discouraged because I couldn't understand it the slightest. I understand a lot more now, just can't find a use for pointers. I know how they work, I just can't find a use for them.


Pointers are very powerful, especially in game developement because you can access a myriad of variables by a single common pointer name. For example...


class OBJECTMANAGER
{
private:
GAMEOBJECT objectlist[50];

public:
GAMEOBJECT *GetObject(int id)
{
return &objeclist[id];
}

};



Then whenever you needed to access a certain game object you would...


//OBJECTMANAGER objectmanager
GAMEOBJECT *anobject = objectmanager.GetObject(10);


It is very useful for looping through a list also as you just call for a new pointer each iteration.

With pointers you can also call new to dynamically create variables at run time and delete them whenever.

I hope it makes sense now.

Share this post


Link to post
Share on other sites
Quote:
Original post by Niddles
Okay so what this does is it creates an array of 50 objects, and a function pointer to return the address of one of those 50 objects. Ugh, that's confusing.


No, it doesn't. The class has an array of 50 instances of the object. Because it is private, you normally cant touch them. Returning a pointer to the start of them, however, allows to do mess around with all 50.

Edit: I'm a little tired and whatnot, see my post two posts down for the correct answer.

Share this post


Link to post
Share on other sites
Quote:
Original post by Niddles
Okay so what this does is it creates an array of 50 objects, and a function pointer to return the address of one of those 50 objects. Ugh, that's confusing.


That's exactly what it does. It's a way of keeping the objects encapsulated while still allowing access to an object when you need it. You could work around this by making the objectlist array global but then that defeats the purpose of using a class at all (use a structure).

What is more common is to have an array of pointers to gameobjects and then allocate them at runtime and return that pointer in the function. Technically you'd be returning a pointer to a pointer. Think about that one for a moment.

The reason why a list of pointers is more common is because it saves memory. When you use the new command on a pointer to an object, it creates that object at the location of the pointer which consumes that much memory. By not allocating (new'ing) memory, you save it for use for other things. Of course nowadays prebuilt computers come standard with 512mb of ram so you can probably argue so what. =)

EDIT: I read it as a function returning a pointer in my haste... a function pointer is something different. For clarification.

Share this post


Link to post
Share on other sites
Here, I wrote this.. is it right?

#include <iostream>
#include <string>
using namespace std;
class weapon {
private:
int id;
string name;
public:
void setid(int fid) { id = fid; }
void setname(string fname) { name = fname; }
int *getwid();
string *getwname();
};
class object {
private:
weapon oweapon[10];
public:
void setoweapon();
int *getwid(int num);
string *getwname(int num);
};
void object::setoweapon() {
for(int a=0; a<10; a++) {
oweapon[a].setid(a);
}
oweapon[0].setname("gun");
oweapon[1].setname("club");
oweapon[2].setname("axe");
oweapon[3].setname("bat");
oweapon[4].setname("chicken");
oweapon[5].setname("crobar");
oweapon[6].setname("whip");
oweapon[7].setname("seven");
oweapon[8].setname("bloop");
oweapon[9].setname("dog");
}
int* weapon::getwid() {
return &id;
}
string* weapon::getwname() {
return &name;
}
int* object::getwid(int num) {
return &oweapon[num].getwid();
}
int* object::getwname(int num) {
return &oweapon[num].getwname();
}
int main() {
object o;
o.setoweapon();
for(int a=0; a<10; a++) {
cout<<o.getwid(a)<<endl;
}
for(int b=0; b<10; b++) {
cout<<o.getwname(a)<<endl;
}
return 0;
}

Share this post


Link to post
Share on other sites
Commented improved version:

#include <iostream>
#include <string>
using namespace std;
class weapon {
private:
int id;
string name;
public:
void setid(int fid) { id = fid; }
// this is not a good practise - the parameter will be copied, e.g.
// "fname" will allocate memory internally each time you pass a string
// void setname(string fname) { name = fname; }
// try using a const reference instead, this will only pass the address
// and also tells the compiler that "fname" won't be modified, so no
// additional memory will be allocated if you pass a string object
void setname(string const & fname) { name = fname; }
// returning pointers is dangerous - don't do it unless it is your intention
// to mess with memory. a pointer can not be distinguished from an array in C++
// int *getwid();
// the "const" tells the compiler that the internal state of the class instance
// won't be modified by the method - we only want to return something
int getwid() const;
// same as above
// string *getwname();
// by returning a const reference we avoid unnecessary copies
string const & getwname() const;
};
class object {
public:
// this constant is public so that users can query the number of entries
static int const MaxWeapon = 10;
private:
// avoid magic numbers!
weapon oweapon[MaxWeapon];
// this should be private and get called in the constructor
void setoweapon();
public:
// in this constructor we setup the names automatically.
object();
// this is a constant that indicates an invalid weapon id.
static int const InvalidWeaponId = -1;
// this is a dummy we return if the user passes an invalid id to getwname()
static string const EmptyName;
int getwid(int num) const;
string getwname(int num) const;
};
void object::setoweapon() {
for(int a=0; a<MaxWeapon; a++) {
oweapon[a].setid(a);
}
oweapon[0].setname("gun");
oweapon[1].setname("club");
oweapon[2].setname("axe");
oweapon[3].setname("bat");
oweapon[4].setname("chicken");
oweapon[5].setname("crobar");
oweapon[6].setname("whip");
oweapon[7].setname("seven");
oweapon[8].setname("bloop");
oweapon[9].setname("dog");
}

// initialise the weapon names on construction
object::object() {
setoweapon();
}

// just return the id
int weapon::getwid() const {
return id;
}
// just return the name
string const & weapon::getwname() const {
return name;
}
// we want to protect the class from invalid calls and check the index for validity:
int object::getwid(int num) const {
if ( num >= 0 && num < MaxWeapon )
return oweapon[num].getwid();
else
// we also want the caller to know that she messed up :)
return InvalidWeaponId;
}
// same as above
string const & object::getwname(int num) {
if ( num >= 0 && num < MaxWeapon )
return oweapon[num].getwname();
else
return EmptyName;
}
int main() {
object o;
// not necessary anymore - the constructor does that
// o.setoweapon();
// use the MaxWeapon constant
for(int a=0; a<object::MaxWeapon; a++) {
cout<<o.getwid(a)<<endl;
}
// use the MaxWeapon constant
for(int b=0; b<object::MaxWeapon; b++) {
cout<<o.getwname(a)<<endl;
}
return 0;
}



If you have questions, let me know.

HTH,
Pat

Share this post


Link to post
Share on other sites
I couldn't imagine not using pointers in c++. They are so incredibly powerful and useful. I would recommend trying to find a use for them so you will feel comfortable with them. Your programming will never be the same.

Share this post


Link to post
Share on other sites
Well there are a number of programming errors. First off, you changed the return type of your object::getwname(int num) from string* to int* when you declared it. The second and third errors are in returning pointers to pointers in your object class when you declared you would be returning a single pointer. See below.


int* object::getwid(int num) {
return oweapon[num].getwid();
}
string* object::getwname(int num) {
return oweapon[num].getwname();
}


I removed the & in front of the variables because you do not want to return the adress of the variable because you previously defined in getwid() and getwname() that you would already be returning the address already.

The next errors aren't compile errors but runtime errors.


for(int a=0; a<10; a++) {
cout<<o.getwid(a)<<endl;
}
for(int b=0; b<10; b++) {
cout<<o.getwname(a)<<endl;
}


Because you are dealing with pointers to variables you can't simply output their values with cout. You must dereference them using the * symbol. Like so. Also note that in your for loop that increments 'b' you should put o.getwname(b) instead of 'a' as you are incrementing that and 'a' already = 10.


for(int a=0; a<10; a++) {
cout<< *o.getwid(a)<<endl;
}
for(int b=0; b<10; b++) {
cout<< *o.getwname(b)<<endl;
}


It should run as expected now. However, in terms of coding this to make it easier to understand and even save you some typing, I would avoid returning pointers of variables that there is only one instance of (eg. returning int* getwid() in class weapon). Instead of having to create duplicate functions in your object class for each weapon function you create. You can simply return a pointer to a specific weapon and then use the pointer to call functions from that class.


class weapon
{
private:
int id;
string name;
public:
int getwid()
{
return id;
}
string getwname()
{
return name;
}
};

class object
{
private:
weapon oweapon[10];
public:
weapon *getweapon(int num)
{
return &oweapon[num];
}
};



Then in main you would call..


for (int a=0;a < 10;a++)
{
weapon *currentweapon = o.getweapon(a);
cout << currentweapon->getwid() << endl;
cout << currentweapon->getwname() << endl;
//or even o.getweapon(a)->getwid() will work but may look confusing.
}


Hope that helps. Good luck in your programming.

Share this post


Link to post
Share on other sites
Pointers are a great tool for a lot of things:

o Polymorphism (access of classes via base classes and derived classes)
o Working on memory (image data, sound data, etc.)
o Callbacks/Delegates

Just imagine the memory as one huge array:

unsigned char ucArray[2000000];

Now imagine the bytes from array position from 1024 up to 2048 would be a image. Another feature: This image is not fixed at position 1024, it can be anywhere inside that array.

How to have a piece of code to access the bytes of the image? Either you need to store the index and have the code know about the array. Or you pass a pointer to the function: Here, you don't need to know anything about an array or offsets. Just use the pointer; it points to the start of a 1024 byte sized block of memory with the image inside.

The pointer can locate the block inside array ucArray, but as well in any other array.

Hm, probably not the best example but it should clarify things a bit.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endurion
Pointers are a great tool for a lot of things:

o Polymorphism (access of classes via base classes and derived classes)
o Working on memory (image data, sound data, etc.)
o Callbacks/Delegates

Just a quick note: you can exercise polymorphism using references as well.

Share this post


Link to post
Share on other sites
And never ever underestimate the danger of using raw pointers, especially if there's no good reason for doing it in the first place.
Rasm's code for example is technically correct, but horribly dangerous and error-prone - observe:

delete [] o.getweapon(10);

The compiler won't complain even though there are three errors hidden in that single line.
Just avoid using raw pointers unless a problem cannot be solved efficiently without them.

Share this post


Link to post
Share on other sites

This topic is 4375 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this