robles1999
robles1999

Reputation: 1

Trying to understand pointers in C++

I am trying to learn C++ on my own using the "Teach Yourself C++ in 24 hours" by Jesse Liberty. I wrote this short program to figure out pointers in C++.

#include <iostream>

void hMany(int count); // hMany function prototype


void hMany(int count){
    
    do {
        std::cout << "Hello...\n";
        count--;
        
        }  while (count >0 );
        
};


int main (int argc, const char * argv[]) {
    

    int counter;
    int * pCounter = &counter;
    
    std::cout << "How many hellos? ";
    std::cin >> counter;
    
    hMany(*pCounter);
    
    std::cout << "counter is: " << counter << std::endl;
    std::cout << "*pCounter is: " << *pCounter << std::endl;
    
    return 0;
}

The resulting output is:

How many hellos? 2
Hello...
Hello...
counter is: 2
*pCounter is: 2

What is the benefit of passing the pointers (*pCounter) vs the argument (counter)?

Any help would be greatly appreciated. Luis

Update:

Ok. The program is working and I now fully understand the C++ pointers. Thank you all for your responses. After trying Chowlett's code I was getting 2 warnings (not errors). One was ! No previous prototype for function hMany and *pCount-- ! Expression result unused. I was able to correct the prototype on my own but I couldn't figure out the *pCount-- warning.

I asked my friend Tony for help and here is his answer.

The parentheses make things happen in the correct order.

(*pCount)--

says to follow the pointer to the integer it points to, and then decrement the integer, which is what you want to do.

*pCount--

ends up doing the wrong thing, the compiler treats it as

*(pCount—)

which says to decrement the pointer first, leaving it pointing to the “integer” before the one you want to change (there is no such thing since you only have one integer you called this function with), then follow this decremented pointer and do nothing with the integer at that memory location. This is why the compiler complained that the expression result was unused. The compiler was correct. This code decrements the pointer incorrectly, fetches the wrong integer, and doesn’t store that wrong integer anywhere.

Here's the correct code for those new to C++ who might be interested.

include

void hMany(int *pCount); // hMany function prototype

void hMany(int *pCount){ // *pCount receiving the address of count

do {
    std::cout << "Hello...\n";
   
    
    // The parentheses make things happen in the correct order.
    // says to follow the pointer to the integer it points to, 
    // and then decrement the integer.
    
          (*pCount)--; 
    
}  while (*pCount >0 );

}

int main (int argc, const char * argv[]) {

int counter;
int * pCounter = &counter;

std::cout << "How many hellos? ";
std::cin >> counter;

hMany(pCounter); // passing the address of counter

std::cout << "counter is: " << counter << std::endl;
std::cout << "*pCounter is: " << *pCounter << std::endl;

return 0;

}

Upvotes: 0

Views: 232

Answers (5)

Chowlett
Chowlett

Reputation: 46667

There is no difference between using *pCounter and counter. In both cases, you are passing the value of the variable counter. However, if you actually pass the pointer itself, you get different behaviour.

Consider the slightly different program:

#include <iostream>

void hMany(int* pCount); // hMany function prototype


void hMany(int* pCount){

    do {
        std::cout << "Hello...\n";
        --*pCount;

        }  while (*pCount >0 );

}


int main (int argc, const char * argv[]) {


    int counter;
    int * pCounter = &counter;

    std::cout << "How many hellos? ";
    std::cin >> counter;

    hMany(pCounter);

    std::cout << "counter is: " << counter << std::endl;
    std::cout << "*pCounter is: " << *pCounter << std::endl;

    return 0;
}

In this case, your output will be:

How many hellos? 2
Hello...
Hello...
counter is: 0
*pCounter is: 0

By passing in the pointer to counter (literally, the address in memory of counter), you allow the function to change counter through its memory location.

Upvotes: 2

Tae-Sung Shin
Tae-Sung Shin

Reputation: 20643

Pointer actually contains memory address with type information of the value that the memory address represents. It may be used to pass the entity in memory address without instantiating it again to change its value or something like that.

But in your program, I can't see any benefit from using pointer because a C++ function, hMany in your case, internally re-instantiate the type of value in its argument, `int count' in your case.

As the other answers pointed out, you need to pass pointer of count to the function instead. In that case, the C++ function will similarly re-instantiate the type of value in its argument, but since the type is pointer, the program will have correct memory address of count inside of the C++ function and can correctly change the value of right identity.

Upvotes: 0

masoud
masoud

Reputation: 56479

int counter;
int * pCounter = &counter;

...

hMany(*pCounter); // Pass by value

hMany(counter);   // Pass by value

What is the benefit of passing the point (*pCounter) vs the argument (counter)?

In this case nothing, it's just an educational example. It shows you can dereference a pointer and get its value by * .

In addition, both cases are passing by value.

In practice you should avoid using pointers by default, unless you have a good reason.

Upvotes: 2

cerkiewny
cerkiewny

Reputation: 2851

The difference is the scope of the variable.

If you pass the variable it is copied to the stack in the local scope of the function. Changing the value is than done in local copy for the function called, if this is the case 1st your using space if the large variable is passed, 2nd you need to return the value from your function (as the stack will be destroyed once you go back)

You can think of it like this:

stack:

current function stack:

[    ]
[    ]
[    ]
[    ]

when you call another 1 element is added

[    ]
[    ]
[    ]
[    ]
[newel]

when you leave the function it is deleted so its like this again

[    ]
[    ]
[    ]
[    ]

newelement value cant be trusted no more.

But if this is the copy of the pointer, you change not the pointer copy value but the value of the place it points too so the stack will be like this

[    ]
[ actual_value]
[    ]
[ pointer_to_value]

than you call the function

[    ]
[ actual_value]
[    ]
[ pointer_to_value]
[ pointer_to_value_copy]

which will change the actual_value on the stack and quit deleting copy of pointer_to_value

[    ]
[ actual_value**changed]
[    ]
[ pointer_to_value]

Upvotes: 0

P0W
P0W

Reputation: 47794

What is the benefit of passing the point (*pCounter) vs the argument (counter)?

There's no "benefit" , this is how you are supposed to pass the value pointed by the pointer pCounter.

hMany(*pCounter) -> dereferences pCounter to get value

Upvotes: 0

Related Questions