I'm making a simple Snake game. When making a map, my definition of the map is as follows
int map[25][25] = { 0 };
for (int i = 0; i < 25; i )//Set the boundary to - 2
{
map[0][i] = -2;
map[24][i] = -2;
}
for (int i = 1; i < 25; i )//Set the boundary to - 2
{
map[i][0] = -2;
map[i][24] = -2;
}
Then I made a function to simulate the motion of the snake。(The first parameter is the class I created: snake,The second is its moving direction. The key is the third parameter, the map array I put in.)
void snake_move(Snake snake1, int direction, int map[][25])
Then I made a call to the function.(The third parameter is the two-dimensional array pointer I passed in)
snake_move(snake1, direction, map);
Then the following figure appears
I found that it was a two-dimensional array before the function call,which is as follows
Why does this happen and how to solve this problem? I look forward to your reply・v・
CodePudding user response:
You cannot pass built-in arrays like this to functions. snake_move()
, even though it appears to have an argument that looks like a 2D array, it actually takes a pointer to a 1D array. This:
void func(int map[][25]);
Is actually equivalent to:
void func(int (*map)[25]);
map
is a pointer to an array of 25 int
elements. When you call that function:
func(map);
The map
array "decays" to a pointer that points to its first element.
This is an unfortunate consequence of C 's compatibility with C.
To avoid issues like this, use std::array (for fixed-size, static allocation of elements), or std::vector (for dynamically allocated elements.)
To get a 2D array, you need to use an array of arrays or a vector of vectors. For an array, that means:
std::array<std::array<int, 25>, 25>
This means "an array containing 25 arrays of 25 int
elements.
It's a good idea to make snake_move
take a const
reference to avoid an unnecessary copy of the whole array. So:
#include <array>
void snake_move(
Snake snake1, int direction,
const std::array<std::array<int, 25>, 25>& map);
// ...
std::array<std::array<int, 25>, 25> map{};
for (int i = 0; i < 25; i ) {
map[0][i] = -2;
map[24][i] = -2;
}
for (int i = 1; i < 25; i ) {
map[i][0] = -2;
map[i][24] = -2;
}
snake_move(snake1, direction, map);
If snake_move()
needs to modify the passed array, then remove the const
.
To reduce the need to write the type over and over again, you can use an alias (with the using
keyword):
using MapType = std::array<std::array<int, 25>, 25>;
void snake_move(Snake snake1, int direction, const MapType& map);
// ...
MapType map{};
// ...
The {}
in the map
declaration will initialize all values to zero. You can also use:
MapType map = {};
which does the same.
CodePudding user response:
You can actually keep the dimension without using std::array
void snake_move(Snake snake1, int direction, int (&map)[25][25]);
https://godbolt.org/z/EYz7hzjTj
Also note it's not a 1D array (i.e. map[0]
is not -2
), the debug window does recognize and shows it's a int[25]*
, it probably just have some bug that fail to display it in the correct format.
CodePudding user response:
Why does this happen
Because of type decay. In particular, in many contexts (including when appearing as a parameter to a function), an array decays to a pointer to its first element. For example:
The type
int [6]
decays toint*
The type
int *[6]
decays toint**
.The type
double [10]
decays todouble*
.The type
int [5][6]
decays toint (*)[6]
.
Thus, in you example, the third parameter int map[][25]
is actually a pointer to an array of size 25
with elements of type int
, ie int (*)[25]
.
how to solve this problem?
You can use std::array
, as shown below:
void snake_move(Snake snake1, int direction,
//----------------------------vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv------->std::array used
std::array<std::array<int, 25>,25> map)
{
}
std::array<std::array<int, 25>,25> map; //sta::array used
If the function snake_move()
doesn't change the passed std::array
, and to avoid unnecessary copying, you can take the std::array
as a reference to const
:
void snake_move(Snake snake1, int direction,
const std::array<std::array<int, 25>,25>& map)
//----------------------------^^^^^-----------------------------------^----->lvalue reference to non-const std::array<std::array<int, 25>,25>
{
}