我试图在C ++中创建一个指向2D(5 X 12)数组的指针数组。 ptr数组有5个元素。每个元素应该保存2D数组的相应行的第一个元素的地址。所以第一个元素应该指向第一行的第一个元素,第二个元素应该指向第二行的第一个元素,依此类推。 我的指针数组的第5个元素似乎指向垃圾值。
代码和输出如下所示。谁能告诉我原因?
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int main( )
{
int rainMatrix[5][12] = {{0}}; //declare and initialize rain matrix
int *matrix_ptr[5] = {NULL};//declare and initialize array of pointers
int **matrix_ptr_ptr = matrix_ptr;
for (int i = 0; i < 5; ++i)
matrix_ptr[i] = &rainMatrix[i][0];
rainGen(matrix_ptr_ptr, 5, 12); //generate a random matrix
//display the matrix
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 12; ++j) {
cout << setw(2) << rainMatrix[i][j] << " ";
}
cout << endl;
}
for (int i = 0; i < 5; ++i)
cout << setw(2) << *matrix_ptr[i] << " " << rainMatrix[i][0] << endl;
return 0;
}
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
**pptr = rv;
*pptr += 1;
}
pptr++;
}
}
输出
11 1
88 11
28 88
25 28
1477892712 25
答案 0 :(得分:1)
您正在修改matrix_ptr
函数中指针数组rainGen
中的指针,以便所有指针都指向结束,并进一步访问“随机”内存位置,即< em>未定义的行为。像valgrind这样的工具可以找到这样的错误。
答案 1 :(得分:1)
你在最里面的循环中操纵错误的指针。仔细考虑指针运算:
pptr
基本上指向matrix_ptr[0]
; **pptr
将设置您想要的内容,但随后*pptr += 1
会修改matrix_ptr[0]
的内容,这意味着它不再指向矩阵的开头。随后通过循环会大大加剧这种情况。
修改pptr
不会有帮助,因为它实际上指的是错误的东西:它指向matrix_ptr
,所以递增仅移动其地址指向matrix_ptr[0]
的{{1}}指向rainMatrix[0][0]
指向matrix_ptr[1]
的{{1}}。这是矩阵的下一个条目的错误地址,即rainMatrix[1][0]
。实质上,您已移至下一行,而不是下一行。
请尝试使用最里面的循环:
rainMatrix[0][1]
在这种情况下,for (int i = 0; i < row; ++i)
{
auto qptr = *pptr;
for (int j = 0; j < col; ++j)
{
rv = rand() % 100;
*qptr = rv;
qptr += 1;
}
pptr++;
}
}
被赋予矩阵中第一个条目的地址。 qptr
设置值。 *qptr = rv
在qptr += 1
单独离开时增加qptr
的位置 - 并且,通过扩展,它会单独留下*pptr
。
答案 2 :(得分:1)
John Perry正确地发现了这个问题,但你有几种方法可以解决它。您错误地递增*pptr += 1
除了使用auto
之外,您只需使用j
的偏移量对指针进行索引,例如
*(*pptr + j) = rv;
或
(*pptr)[j] = rv;
要么工作。将它放在rainGen
函数中,您可以这样做:
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
// *(*pptr + j) = rv; /* or */
(*pptr)[j] = rv;
}
pptr++;
}
}
(注意: seed
和srand(seed)
如果有可能多次调用main()
,则应移至rainGen
- srand
只应调用一次)
示例使用/输出
两者都会产生所需的输出:
$ ./bin/raingen
72 71 65 94 0 13 49 17 36 49 67 51
87 68 45 15 91 72 16 80 77 35 9 81
11 88 73 59 24 22 37 48 45 54 94 45
19 44 62 56 45 81 59 32 49 4 99 92
28 16 24 5 3 34 38 14 22 12 26 98
72 72
87 87
11 11
19 19
28 28