在c ++中获取垃圾值的指针数组

时间:2018-05-02 04:22:38

标签: c++ arrays pointers

我试图在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

3 个答案:

答案 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 = rvqptr += 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++;
    }
}

注意: seedsrand(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