-
double pointer problem
Okay, well I am having some problems with double pointers. Now, I am hardly a programming expert and I would be the first to admit it. First off this is not homework. I can use a normal pointer okay and have had no problems doing this, but I have actually never used double pointers either in my programming classes when I was in college or in my job. I recently was asked about this though in a job interview even though the job never said anything about C or C++ expect for it would be nice to have C#. That's microsoft for you. I would like to understand this so in case I ever get asked this again.
Anyway I was given this below which I totally flubbed.
Code:
void Reverse(char* str, char** rev)
Since then about a week now I have tried to learn how to use the double pointer but have not had much luck. So, I thought maybe someone here could help me understand what I am doing wrong. I can get the same function with a normal pointer working find, but not using a double pointer. The code is below.
Oh, the function Reverse2 is what I am having trouble with.
:confused:
Code:
#include <iostream>
#include <string>
using namespace std;
int strlen(char* str)
{
int count = 0;
while( *str++ != '\0')
{
count++;
}
return count;
}
void Reverse(char* str, char* rev)
{
int ptrcnt = 0;
ptrcnt = strlen(str)-1;
cout << "ptrcnt: " << ptrcnt << endl;
for(int i=ptrcnt; i >= 0; i--)
{
*(rev++) = *(str+i);
}
*rev = '\0';
}
void Reverse2(char* str, char** rev)
{
int ptrcnt = 0;
ptrcnt = strlen(str)-1;
cout << "ptrcnt: " << ptrcnt << endl;
for(int i=ptrcnt; i >= 0; i--)
{
**(rev++) = *(str+i);
}
**rev = '\0';
}
int main()
{
cout << "Hello world!" << endl;
char* string1 = new char;
char* string2 = new char;
char** string3 = new char*;
string3 = &string2;
cin.getline(string1, 80);
cout << string1 << endl << endl;
//Reverse(string1, string2);
//Reverse2(string1, string3);
Reverse2(string1, &string2);
cout << string1 << endl;
cout << string2 << endl;
delete string1;
delete string3;
delete string2;
return 0;
}
-
Code:
#include <iostream>
#include <string>
using namespace std;
// Why would you write your own strlen function???
// I canned it.
void Reverse2(char* str, char** rev) {
// I've moved the allocation of space into this routine since that makes
// more sense (otherwise why are you bothering to pass a double pointer?)
// Actually, it would make more sense to return the pointer but....
size_t len = strlen(str);
*rev = new char[len];
// If you're going to walk the given pointer through the array
// then you'd better make a copy of it (otherwise you'll alter the original).
char *p = *rev;
for(int i = len - 1; i >= 0; i--)
*p++ = str[i];
*p = '\0';
}
int main() {
// Why are you only allocating one char of space???
char *string1 = new char[81]; // Need more that one char of space!!!
char *string2; // I moved allocation of this space into Reverse2 ... for fun.
cin.getline(string1, 80);
Reverse2(string1, &string2);
cout << string1 << endl;
cout << string2 << endl;
delete [] string1;
delete [] string2;
}
-
Quote:
Originally Posted by
oogabooga
Code:
#include <iostream>
#include <string>
using namespace std;
// Why would you write your own strlen function???
// I canned it.
void Reverse2(char* str, char** rev) {
// I've moved the allocation of space into this routine since that makes
// more sense (otherwise why are you bothering to pass a double pointer?)
// Actually, it would make more sense to return the pointer but....
size_t len = strlen(str);
*rev = new char[len];
// If you're going to walk the given pointer through the array
// then you'd better make a copy of it (otherwise you'll alter the original).
char *p = *rev;
for(int i = len - 1; i >= 0; i--)
*p++ = str[i];
*p = '\0';
}
int main() {
// Why are you only allocating one char of space???
char *string1 = new char[81]; // Need more that one char of space!!!
char *string2; // I moved allocation of this space into Reverse2 ... for fun.
cin.getline(string1, 80);
Reverse2(string1, &string2);
cout << string1 << endl;
cout << string2 << endl;
delete [] string1;
delete [] string2;
}
Thanks a lot. It has been awhile since I have used pointers. I was using C# for the last couple of years. Obviously I need to revisit pointers if I intend to do anything with C or C++. I made my own strlen because the C++ string library does not have it so I had to either make my own which was not difficult or include string.h. I had thought about the size when I was initially declaring string1, but the original version of Reverse without double pointers worked and it seems to work either way, but declaring it with is probably the correct way. As to why use a double pointer in the first place, well that was the problem I was given and not my choice. Anyway, thanks.
This is my new modified function which now works :
Code:
void Reverse2(char* str, char** rev)
{
int len = strlen(str);
*rev = new char[len];
char *temp = *rev;
for(int i=len-1; i >= 0; i--)
{
*temp++ = *(str+i);
}
*temp = '\0';
}
-
Note that line 5 of your latest example should be
Code:
*rev = new char[len + 1];
to add space for the NULL terminator, otherwise you have an off-by-one error. A buffer overrun. (Imagine a string of length 0 is passed in. Okay, you go new char[0], then the loop doesn't execute, but you still try to set *temp='\0'....)
As you've discovered, you have to be very careful about incrementing double pointers. If you have char **rev, which is pointing at some string char *p elsewhere, then **(rev++) really means to make rev point at the pointer following p in memory, which is probably not what you want (even undefined)... Your latest code essentially does *(*rev++), which makes more sense: follow rev to get to p, then post-increment p, and dereference p to get the character it points to. I know you've already figured it out, just thought an explanation of the syntax might be helpful. If you still have trouble then drawing the pointers out on a sheet of paper can be quite helpful! Cheers.
-
In C, a double pointer usually indicates one of two things:
1. Somebody is passing a pointer "by reference." Using pointers is the only way to get reference-like parameter passing in C. If the thing you are passing is itself a pointer, the resulting thing is a pointer-to-pointer. This is the case in your string-reverse example.
2. Somebody is using an array of pointers.
Both of these cases should hopefully be easy enough to understand. So when you see a pointer-to-pointer, first figure out WHY it is being used, then it should become more clear. People don't (or at least shouldn't) be using them for no good reason.
I have, precisely once, seen a legitimate use of a triple pointer. And quadruple pointers and up are theoretical, as far as I'm concerned.