Jump to content
  • Advertisement
Sign in to follow this  
PineBark

Pointer problems

This topic is 4146 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, I've been aching with a few things about pointers lately. char* GetName() { return name; } while char name[10]; is a member of the same class as the GetName() function. Now i've always been confused by pointer functions. What does it return? A pointer to the name? Another thing was the weirdness with passing in variables to functions who accept pointers. Like: void SetName(char* newname) { strcpy(name, newname); } So when i pass something into the func like this: SetName("Foobar!"); it copys it from newname to name, but shouldn't newname be equal to the addres of the word "Foobar!" rather than it's value (which is "Foobar!" :P) and I don't need to use *newname? And a similar thing with passing in classes: void DoStuff(KLASS* klass) { cout << klass->name << endl; } and when I pass in the realcass instance of KLASS like this : DoStuff(realklass); it throws an error at me saying that it can't convert from KLASS to *KLASS, while if i pass in the addres of realklass (DoStuff(&realklass);) it works perfectly. I've been assuming that the -> sign needs the address of the class so it could use variables from it, ok, but why is it totaly different with normal variables? :S Thank you for your time.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by PineBark
Hey, I've been aching with a few things about pointers lately.

char* GetName() { return name; }
while char name[10]; is a member of the same class as the GetName() function. Now i've always been confused by pointer functions. What does it return? A pointer to the name?


Specifically, a pointer to the start (first character) of the array "name".

Quote:
Another thing was the weirdness with passing in variables to functions who accept pointers. Like:
void SetName(char* newname) { strcpy(name, newname); }
So when i pass something into the func like this: SetName("Foobar!"); it copys it from newname to name, but shouldn't newname be equal to the addres of the word "Foobar!" rather than it's value (which is "Foobar!" :P) and I don't need to use *newname?


Indeed. strcpy dereferences newname to get the values of each character that newname points to the start of.

Also of note, since you're using C++, std::string will take a lot of hassle out of the daily chore of string memory management.

Quote:
And a similar thing with passing in classes:
void DoStuff(KLASS* klass) { cout << klass->name << endl; }
and when I pass in the realcass instance of KLASS like this : DoStuff(realklass); it throws an error at me saying that it can't convert from KLASS to *KLASS, while if i pass in the addres of realklass (DoStuff(&realklass);) it works perfectly.


Right. Values (such as realclass) are not implicitly convertable to pointers -- note that "Foobar!" already is an array of characters (which is implicitly convertable to a pointer to the first character).

Quote:
I've been assuming that the -> sign needs the address of the class so it could use variables from it, ok, but why is it totaly different with normal variables? :S

Thank you for your time.


Not quite sure I grok this final question. In reality, operator. also uses the address of a class implicitly. (*pointer).variable, pointer->variable, reference.variable, value.variable -- these all do (basically) the same thing.

Share this post


Link to post
Share on other sites
1) dont use pointers use references instead :)

2) Dont use char*'s use std::string instead

3)
Quote:
char* GetName() { return name; }
while char name[10]; is a member of the same class as the GetName() function. Now i've always been confused by pointer functions. What does it return? A pointer to the name?


Arrays decay to pointers to the first element of the array so GetName returns a pointer to the first character in the name.

Quote:
Another thing was the weirdness with passing in variables to functions who accept pointers. Like:
void SetName(char* newname) { strcpy(name, newname); }
So when i pass something into the func like this: SetName("Foobar!"); it copys it from newname to name, but shouldn't newname be equal to the addres of the word "Foobar!" rather than it's value (which is "Foobar!" :P) and I don't need to use *newname?


Once again use a const std::string& instead. Yes newname is equal to the address were "Foobar!" is stored. strcpy takes two pointers and copies the chars at the first into thesecond until it finds a char in the first that is qual to '\0' so it does the dereference for you.

Quote:
And a similar thing with passing in classes:
void DoStuff(KLASS* klass) { cout << klass->name << endl; }
and when I pass in the realcass instance of KLASS like this : DoStuff(realklass); it throws an error at me saying that it can't convert from KLASS to *KLASS, while if i pass in the addres of realklass (DoStuff(&realklass);) it works perfectly. I've been assuming that the -> sign needs the address of the class so it could use variables from it, ok, but why is it totaly different with normal variables? :S


Its no different with normal variables. Here you are passing a pointer to the class so you have to dereference it before you can call a member function on it.
myClassPtr->MemFunc(); is simpily short hand for (*myClassPtr).MemFunc();
You dont have to pass classes by pointer its perfectly valid to pass then by value...


// these oth pass pointers and modify the origonal object
void DoStuff(MyClass* myclass) { myclass->somefunc(); }
void DoStuff(int* myint) { *myint = 3; }

// these pass by value leaving the origonal unchanged
void DoStuff(MyClass myclass) { myclass.somefunc(); }
void DoStuff(int myint) { myint = 3; }


Hope that helps.

Share this post


Link to post
Share on other sites
Pointers are tricky, allright. I'll answer your questions, as well as point out a great alternative to char*'s when toying with strings.

Quote:
Original post by PineBark
char* GetName() { return name; }
while char name[10]; is a member of the same class as the GetName() function. Now i've always been confused by pointer functions. What does it return? A pointer to the name?

Yup, it returns the address of the first character in the array, or the address of name[0], or &name[0]. It's up to you to deal with it appropriately.

Quote:

Another thing was the weirdness with passing in variables to functions who accept pointers. Like:
void SetName(char* newname) { strcpy(name, newname); }
So when i pass something into the func like this: SetName("Foobar!"); it copys it from newname to name, but shouldn't newname be equal to the addres of the word "Foobar!" rather than it's value (which is "Foobar!" :P) and I don't need to use *newname?


newname would be equal to the address of the word "Foobar!" (which would just be somewhere in memory, and not guaranteed to stick around if it's just being sent to a function) if you were to say
name = newname
with both name and newname being char*'s. That's where strcpy comes in. It copies each character from one string into another, thereby "copying" it, not just making another reference (pointer) to the same string.

As to using "*newname" -- when would you use that? In the call to strcpy? Both of strcpy's parameters are pointers. If you dereferenced newname, it would no longer be a pointer, but a char (Since it is a pointer to a char. If it were a pointer to a pointer, this would be a different matter.). In the function declaration for SetName, where the '*' is placed does not matter -- it could be either void SetName(char* newname) or void SetName(char *newname). I prefer the latter, as it makes clear what "newname" is (a pointer to a char).

Quote:
And a similar thing with passing in classes:
void DoStuff(KLASS* klass) { cout << klass->name << endl; }
and when I pass in the realcass instance of KLASS like this : DoStuff(realklass); it throws an error at me saying that it can't convert from KLASS to *KLASS, while if i pass in the addres of realklass (DoStuff(&realklass);) it works perfectly. I've been assuming that the -> sign needs the address of the class so it could use variables from it, ok, but why is it totaly different with normal variables? :S


The -> operator is used when accessing members of a variable. Since primitive types like ints and chars don't have members, they have no use for the -> operator. Classes and structs, types with members, use the -> and '.' operators, -> when the variable is a pointer to a class or struct, and '.' when the variable is a class or struct.

This is just the most basic of basics when it comes to pointers. As tricky as this is, it doesn't stop there. [smile] Pointers, and char*'s in particular, are susceptible to buffer overrun attacks. If you allocate a buffer of size 10 (like in your example above), but someone gives you 15 characters as a name, those extra characters can overwrite memory and (at best) do nothing, (usually) crash the program, or even (at worst) change the control path of the program and execute malicious code. Dynamic memory allocation is even trickier. Assuming C++, here, a simple, effective, and safe way to get by without such possible dangers is to use a part of the standard library, like a std::string. Take the following code:
//  in some class, "name" is declared a std::string

// not much difference here...
std::string GetName( ) { return name; }

// but HERE is where the beauty shines
void SetName(const std::string& newname) { name = newname; }
// There's no need to use strcpy. Operators work (for the most part) just like you'd expect
// There's no need to worry about buffer overflow attacks. std::strings resize themselves



As an exercise in pointers, you're on the right track. In actual production code, though, you can save a lot of headaches by using good tools. std::string is one such tool. [smile]

Hope this helps!
-jouley

[Edit: GD's back up to full speed, but I'm not...]

Share this post


Link to post
Share on other sites
Thanks a lot for the responses, I understand much more than I did before, I think, but it's still a bit cloudy in my head.
I'll throw an observation out there:

void DoStuff(char* var) { cout << var << endl; }
Assume I do DoStuff("foo!");. Now, it outputs the word "foo!" on the screen. If I did cout << *var; instead it'll ouput the first letter, which makes sense since var is the pointer to the first letter, and if I do cout << &var; it outputs something which is either the address of "foo!" or the address of the pointer itself (? :o). The strange thing is that while *var is = "f" and &var is = address of smth, var is = "foo!". Now how does that work? I thought that var without any prefixes should be the address, or is it really the address, but it get's dereferenced whenever you use it, and you have to do &var to actually get the address of the variable you passed in without it getting dereferenced?

And I will have a look at string's, never really used them. Though I'd like to figure this out with char's first.

Share this post


Link to post
Share on other sites
std::ostream& operator<<(std::ostream&,const char*) is overloaded: it prints the pointed-at memory area as if it were a C-string, instead of printing an integer representation of the address as with other pointer types.

2° In char var[N], var is an array. Arrays are not pointers, they're an independent type which allows subscript read-write operations. The variable var (as all arrays) may decay to a pointer to the first element when used in a context where a pointer is necessary.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
std::ostream& operator<<(std::ostream&,const char*) is overloaded: it prints the pointed-at memory area as if it were a C-string, instead of printing an integer representation of the address as with other pointer types.


Just to expand on this with an example:

const char * var = "Hello World!";

std::cout << *var << std::endl;
//will print the first character

std::cout << (const void*) var << std::endl;
//will print the address of the first character -- (const void*) gets rid of the
//special treatment (const char*) gets -- namely, it's interpreted as the start of
//a C-style string and prints the string out instead of the address

std::cout << &var << std::endl;
//will print the address of where the var pointer itself is -- &var yields:
// (const char**)

Share this post


Link to post
Share on other sites
Ahh... Now I get it. I had some confusion about what the var itself was and how it got handled.

Though I'm still not completely sure about pointing to classes. Taking the earlier example:

void DoStuff(KLASS* klass) { cout << klass->name << endl; }
KLASS someclass;
DoStuff(&someclass);

So in this case, because it can't extract what it needs from someclass and make a pointer of it itself, you have to pass in the address directly?

Shouldn't you be able to pass in addresses of normal variables when dealing with them instead of classes?

Thanks a lot for all the help, this'll be my last post if I get my questions answered. Rating++ for all.

Share this post


Link to post
Share on other sites
So in this case, because it can't extract what it needs from someclass and make a pointer of it itself, you have to pass in the address directly?

Shouldn't you be able to pass in addresses of normal variables when dealing with them instead of classes?


I'm not sure exactly what you mean here as you can pass the address of normal variables, maybe an example of that would help you?

void DoStuff(int* intPtr) 
{
cout << "Address of int: " << intPtr << "Value of int: " << *intPtr << endl;
}

int myInt = 8;
// prints: "Address of int: 0xnumber Value of int: 8"
// number is the address of myInt
DoStuff(&myInt);

Share this post


Link to post
Share on other sites
Quote:
Original post by Julian90
I'm not sure exactly what you mean here as you can pass the address of normal variables, maybe an example of that would help you?
[snip code]

Uh oh, I'm dead wrong then! It must be a char thing, since if you'd replace integers with char's in your example:

void DoStuff(char* charPtr) {
cout << "Address of int: " << charPtr << "Value of int: " << *charPtr << endl;
}
char myChar = "LOL!";

DoStuff(myChar);

You could no longer do DoStuff(&myChar), but the DoStuff(myChar) would work. Chars + Pointers confuse me :S

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!