0

I am developing a tic-tac-toe board game in c++ for learning purposes, and I am passing a char** to a function that assigns the given parameter an array of pointers which stores a players name.

Upon variable assignment, I am able to print the results of the initialized variable in the function call to void initPlayerNames(char** playerNames) but when I return to the caller function the program does not print the results.

My understanding is that a pointer variable stores the address of another data structure, therefore I expect to print the results of the pointer variable after it has been modified in the function call.

Please help me understand where I am making a mistake

void initPlayerNames(char** playerNames) {
   const int playerNameLength = 100; 

   cout << "Player one, enter your name: "; 
   char p1[playerNameLength];
   cin.getline(p1, playerNameLength);

   cout << "Player two, enter your name: "; 
   char p2[playerNameLength]; 
   cin.getline(p2, playerNameLength);

   char* names[2] = {p1, p2}; 
   playerNames = names; 

   cout << "Player 1 = " << playerNames[0] << endl; 
   cout << "Player 2 = " << playerNames[1] << endl; 

}; 

void game() {

   char** playerNames = nullptr; 
   cout << "Welcome! \n";  

   initPlayerNames(playerNames); 
   cout << "Player 1 = " << playerNames[0] << endl; 
   cout << "Player 2 = " << playerNames[1] << endl; 

};

Output

Player one, enter your name: Kevin Patel

Player two, enter your name: Steve Jobs

Player 1 = Kevin Patel

Player 2 = Steve Jobs

  • 1
    Did you try stepping through the code with a debugger? – Quimby Jan 25 '22 at 20:23
  • A couple problems here, and the first will sound really funny. When you pass an object by a pointer, the object is passed by reference, but the pointer itself is still passed by value. If you need to update where the pointer points, the pointer must also be passed by reference otherwise in the function a copy of the pointer is re-pointed and the calling argument is unaware of the change. – user4581301 Jan 25 '22 at 20:24
  • yes i am using linux gdb compiler online via https://www.onlinegdb.com/ and when I stepped through the code I inserted a breakpoint after the call to `initPlayerNames` and noticed that `playerNames` was not pointing to the data that it was assigned in the function call – kevinjaypatel Jan 25 '22 at 20:27
  • Once you get the first problem sorted out you'll find the second: The code assigns a pointer to a local variable to `playerNames`. This local variable will go out of scope at the end of the function, leaving `playerNames` pointing to an expired object. [Maybe the object will look like it's still there](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope), but it's not and sooner or later it won't be. – user4581301 Jan 25 '22 at 20:28

1 Answers1

2

The pointer playerNames is set like this:

   char* names[2] = {p1, p2}; 
   playerNames = names; 

However, when the function initPlayerNames() exits, names, p1and p2 are all destroyed and thus playerNames points at unallocated memory.

Besides, playerNames itself in initPlayerNames() is a variable which is destroyed when the function exits (like in a function void func(int a), changes to a are not reflected in the caller function).

To fix this:

  1. Declare the involved variables as static which means they will be allocated also when the function is not running. Note, however, that this is mostly to illustrate the lifetime issue, this solution is not without problems (not safe in multi-threaded applications and exposes seemingly local variables outside their function - it is like using global variables).

  2. Pass a pointer or reference to playerNames. Being old-fashioned, I prefer a pointer so it is clearer that the passed argument may be changed:

void initPlayerNames(char*** playerNames) {
   const int playerNameLength = 100; 

   cout << "Player one, enter your name: "; 
   static char p1[playerNameLength];
   cin.getline(p1, playerNameLength);

   cout << "Player two, enter your name: "; 
   static char p2[playerNameLength]; 
   cin.getline(p2, playerNameLength);

   static char* names[2] = {p1, p2}; 
   *playerNames = names; 

   cout << "Player 1 = " << (*playerNames)[0] << endl; 
   cout << "Player 2 = " << (*playerNames)[1] << endl; 

};

and call the function like this:

   initPlayerNames(&playerNames);    
nielsen
  • 5,641
  • 10
  • 27