【问题标题】:Scanf and Dynamic memory allocationScanf 和动态内存分配
【发布时间】:2020-04-21 23:19:17
【问题描述】:
int **elem;
elem = (int **)malloc(sizeof(int**) * numCol);

        for (i = 0; i < 2; i++)
        for (j = 0; j < numCol; j++)
        {
            scanf("%d", &elem[i][j]); //Shouldn't it give a value to the address pointed by 
                                     //a pointer to pointer to int?

        }

为什么这段代码会给出分段错误错误?(分段错误:11) 这段代码有效:

int **elem;
elem = (int **)malloc(sizeof(int**) * numCol);

        for (i = 0; i < 2; i++)
        {
        elem[i] = (int *)malloc(numCol * sizeof(int));

        // Fill it with values

        for (j = 0; j < numCol; j++)
        {
            scanf("%d", &elem[i][j]);
        }

我很困惑。除了分割问题之外, int ** 的值不是 4 吗?为什么不直接使用 int。

【问题讨论】:

  • int *int ** 很可能具有相同的大小,但你真的应该写 elem = malloc( numCol * sizeof *elem )elem = malloc( numCol * sizeof(int *))。我更喜欢前者,因为它很好地避免了这个特殊的错误。请注意,强制转换是不必要的,并且可能存在问题。
  • 许多编程错误是由于假设指针具有与整数相同的大小,还有许多其他错误是因为假设大小为 4。也许在您的机器上sizeof (int) == sizeof (int *) == 4,但是在所有机器上肯定不是这样。

标签: c matrix scanf dynamic-memory-allocation


【解决方案1】:

第一个代码 sn-p 段错误,因为您没有为数组列分配任何内存 - 每个 elem[i] 都没有指向任何有意义的东西。

像这样分配“锯齿状”数组的一般模式如下:

/**
 * Allocate N "rows", which is actually an array of 
 * pointers to T
 */
T **arr = malloc( sizeof *arr * numRows ); // for any type T
if ( arr )
{
  /**
   * For each "row", allocate an array of T
   */
  for ( size_t i = 0; i < numRows; i++ )
  {
    arr[i] = malloc( sizeof *arr[i] * numCols );
    if ( arr[i] )
    {
      for ( size_t j = 0; j < numCols; j++ )
      {
        // initialize arr[i][j]
      }
    }
  }
}

图片可能会有所帮助。

首先你从arr指针开始:

     T **
     +–––+
arr: |   |
     +–––+

然后你分配一个指向T的指针数组作为你的“行”(为了保持图片的合理大小,我们假设两行两列):

     T **      T *
     +–––+     +–––+
arr: |   | ––> |   | arr[0]
     +–––+     +–––+
               |   | arr[1]
               +–––+

最后你为每个“行”分配T的数组:

     T **      T *               T
     +–––+     +–––+             +–––+
arr: |   | ––> |   | arr[0] –––> |   | arr[0][0]
     +–––+     +–––+             +–––+
               |   | arr[1] –+   |   | arr[0][1]
               +–––+         |   +–––+
                             |
                             |   +–––+
                             +-> |   | arr[1][0]
                                 +–––+
                                 |   | arr[1][1]
                                 +–––+

不能保证 sizeof (int **)sizeof (int *)sizeof (int) 相同(在 x86_64 上,指针大小通常为 8 个字节)。

请注意,通过这种零散分配,行在内存中不会是连续的 - arr[1][0] 不会立即跟随 arr[0][1]

【讨论】:

    【解决方案2】:

    我很困惑。除了分割问题之外,int ** 不给出一个 价值4?为什么不直接使用 int。

    并非在所有机器上都是如此,因此在 sizeof 函数中使用正确的类型是正确的,以避免在程序运行时复杂地发现错误。

    为什么这段代码会出现分段错误?(分段错误:11) 这段代码有效吗?

    第一段代码在为int** elem 动态分配内存时出错,实际上您只在矩阵中分配了一行。

    在第二个代码中,您对矩阵进行了正确的初始化。 注意在第二个代码中你的循环是为 inumCol 等于 2 时,此初始化才是正确的。

    更好的代码可以是这样的:

    int **elem;
    elem = (int **)malloc(sizeof(int*) * numCol); //a correction in sizeof
    
            for (i = 0; i < numCol; i++) //cycle on numCol and not on 2
            {
                elem[i] = (int *)malloc(numCol * sizeof(int));
    
                // Fill it with values
    
                for (j = 0; j < numCol; j++)
                {
                    scanf("%d", &elem[i][j]);
                }
     }
    

    【讨论】:

    • 我已经测试过我的 int* 和 int** 的大小是 8 而 int 是 4。它们是不同的。
    • 难道 int** 不是说我们想要分配一个二维数组吗?只是问。为什么要使用 int **?。
    • int** 是一个指向 int 的指针。并且它可以用于二维数组但不仅仅用于这个。我给你留了一个有用的链接:C-pointer to pointer
    • 顺便说一句,我写 i
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2012-08-09
    • 2012-01-13
    • 2021-04-15
    • 2020-04-30
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多