【问题标题】:Array of Pointers getting garbage value in c++在 C++ 中获取垃圾值的指针数组
【发布时间】:2018-05-02 14:07:13
【问题描述】:

我正在尝试在 C++ 中创建一个指向 2D (5 X 12) 数组的指针数组。 ptr 数组有 5 个元素。每个元素都应保存二维数组相应行的第一个元素的地址。所以第一个元素应该指向第一行的第一个元素,第二个元素应该指向第二行的第一个元素,依此类推。 我的指针数组的第 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

【问题讨论】:

  • 我读对了吗?您是否将指针设置为 rv = rand() % 100; 中的随机值? **pptr = rv; ?
  • @DenizC 不,他正在将指针的内容设置为随机值。
  • @JesperJuhl,真的。我忘了删除我的评论。

标签: c++ arrays pointers


【解决方案1】:

您在最里面的循环中操作了错误的指针。仔细考虑指针算法:

  • pptr本质上指向matrix_ptr[0]
  • 第一次迭代中,双重间接意味着**pptr会设置你想要的,然后
  • *pptr += 1 将修改 matrix_ptr[0] 的内容,这意味着 它不再指向矩阵的开头

随后通过循环使情况急剧恶化。

修改pptr 不会有任何帮助,因为它实际上指向了错误的东西:它指向matrix_ptr,所以增加它仅仅一次会从matrix_ptr[0] 移动它的地址,这指向rainMatrix[0][0],指向matrix_ptr[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 - 并且,通过扩展,它单独留下matrix_ptr[0]

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

    • 我回答的重点不是auto而是qptr的使用。虽然等同于您的答案,但我认为这两种方法都可以让经验不足的程序员更清楚地表达意图,并且不太容易出现像这样的指针算术错误。
    • 同意。当您发布答案时,我只是在搞乱这一部分。印象深刻。 auto 不是我的第一个想法,但效果很好。组合应该给出一个清晰的画面。谢谢。
    【解决方案3】:

    您正在修改 rainGen 函数中的指针数组 matrix_ptr 中的指针,以便所有指针都指向末尾,进一步访问“随机”内存位置,这是 未定义的行为。 valgrind 等工具可以发现此类错误。

    【讨论】:

    • 具体来说,声明*pptr += 1; 可以这么说。
    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多