David Griffith
David Griffith

Reputation: 27

Setting class level 2D Array variable to passed in value - C++

I'm attempting to make a maze-solving program, and while the algorithm is sound (at least in my head), I've been running into a roadblock with 2D arrays. I'm coming from C# and Java, so the syntax is giving me grief.

Here's an SSCCE:

//Main.cpp

#include "MazeSolver.h"

int main()
{
     MazeSolver mazeSolver;

     char maze[51][51] = { }; // Not bothering to show code for populating the array

     mazeSolver.setMaze(maze);
}

//MazeSolver.cpp

#include "MazeSolver.h"

MazeSolver::MazeSolver() { }

void MazeSolver::setMaze(char maze[51][51])
{
     this->maze = maze;
}

//MazeSolver.h

#ifndef _MAZESOLVER_H
#define _MAZESOLVER_H

class MazeSolver
{
private:
     char **maze; // This is likely the problem, I'm at wits end in regards to
                  // what notation is needed here.  I do not want to hard-copy
                  // the entire array, I just need to access it (via pointer)
                  // I've also tried just using char maze[51][51] here, char *maze, etc...
public:
      MazeSolver();
      void setMaze(char maze[51][51]);
}

Upvotes: 1

Views: 260

Answers (2)

IdeaHat
IdeaHat

Reputation: 7881

<rant>

This is one of the weird quirks of C++.

C++ 2D arrays are NOT jagged arrays. When you declare char maze[51][51], it actually allocates 1 contiguous array 51*51 members long. sizeof(maze) == 51*51. When you dereference a value, maze[a][b], what it actually does is *(maze+51*a+b). All this is under the hood.

A Jagged Array is an array of arrays, a char**. In this case, you have an array of 51 pointers size == (51*sizeof(void*)). In each position, the pointer points to a completely different memory location, allocated to 51 members long.

This is ANNOYING because you can't just convert the two, even by casting. You have to deal with weird syntax, such as char (*maze)[51] to get a pointer to the 2D array.

Whats even more annoying is the following happens:

int foo(int maze[51][51])
{
   return sizeof(maze);
}

int maze[51][51];

int main(int argc, char** argv)
{
   std::cout << sizeof(maze) << std::endl;//return 51*51*sizeof(int);
   std::cout << foo(maze) << std::endl;//return 8, sizeof(void*);
}

So it implicitly passes by reference, not by value, which is opposite all the rest of C++.

</rant>

tl;dr;

The correct syntax for a pointer to a 2D array is char (*maze)[51];. Your syntax is for a jagged array (arrays of arrays) which is NOT the same thing in C++.

Upvotes: 1

Manu343726
Manu343726

Reputation: 14184

You cant assign (Or convert) 2d arrays (array[ROWS][COLUMNS]) to pointers to pointers (aka **) because the memory layout of a 2d array is (could be) very different to the memory layout the pointer of pointers could point to.

Check this thread for more info about this topic.

If suggest you to use the de facto C++ standard container, std::vector, instead of a plain array:

class MazeSolver
{
    std::vector<std::vector<char>> maze;

    void setMaze( const std::vector<std::vector<char>>& new_maze )
    {
        maze = new_maze;
    }
};

Note that a vector has size 0 by default (At the point of its initialization), so you should fill it with elements:

for( std::size_t i = 0 i < ROWS ; ++i )
{
    maze.push_back( std::vector<char>() );

    for( std::size_t j = 0 ; j < COLUMNS ; ++j )
       maze[i].push_back( ' ' );
}

However, C++11 (The current iteration of the language) has a std::array container which is like a C array but with the interface of other Standard Library Containers:

std::array<char,ROWS*COLUMNS> maze;

Upvotes: 2

Related Questions