【问题标题】:why does this for loop iterating over 2d array not work为什么这个循环遍历二维数组不起作用
【发布时间】:2021-09-17 22:50:45
【问题描述】:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main(void)
{

    int a[4][5] =
    {
       {1,1,0,1,0},
       {0,0,0,0,0},
       {0,1,0,0,0},
       {1,0,1,1,0}
    };

    int *ptr = &a[0][0];

    for (; ptr < ptr+19; ptr++)
    {
        printf("%d ", *ptr);
    } 
  
    return 0;
    
}

为什么这段代码不起作用?据我所知,二维数组以行主要顺序存储,如下所示:

[1,1,0,1,0]-[0,0,0,0,0]-[0,1,0,0,0]-[1,0,1,1,0]

所以如果我从 &a[0][0] 开始并每次将其递增 1 直到它递增到最后一个元素,为什么这不起作用?

【问题讨论】:

  • ptr 总是小于ptr+19,至少在指针跑出地址空间的末尾并回绕之前,但它很可能在此之前指向无效内存。
  • “不起作用”不是一个有用的陈述。 做什么它做什么?
  • 除了明显的错误ptr &lt; ptr+19 之外,不允许您以这种方式取消引用数组。您超出了数组访问的范围,这是未定义的行为。允许编译器发疯并生成奇怪的代码或崩溃的程序。

标签: c for-loop pointers multidimensional-array casting


【解决方案1】:

除了使用不同类型的指针访问数据带来的危险之外,循环条件是错误的。

ptr+19ptr 一起移动,条件ptr &lt; ptr+19 将始终为真(直到发生溢出)。

如果您保留原点指针并将其用于停止条件,您的代码会更好。

    int *ptr = &a[0][0];
    int *start_ptr = ptr;

    for (; ptr < start_ptr+19; ptr++)
    {
        printf("%d ", *ptr);
    }

【讨论】:

  • 等一下ptr+19每次都给指针加19?!
  • @programmer29874 是...或者可能不是,因为条件ptr &lt; ptr+19 可能会被优化器转换为无条件的“真”。
  • 哇,我没有意识到迈克非常感谢,你似乎是 C 的专业人士,你能推荐我一些东西来提高 C 的水平吗?也许是一本书或一些材料;P
  • @programmer29874 试试int: for (int x = 0; x &lt; x + 19; x++) printf("%d ", x);。你认为它应该做多少次迭代?
  • @programmer29874:这不是真正的 C 问题。只是数学表达式x &lt; x + y,其中0 &lt; y 始终成立,无论它是程序的一部分还是只是一些手动执行的算术。循环的条件部分在每次迭代时被评估whole。编译器不是看到像a &lt; b 这样的表达式并且认为“哦,我必须重新评估b 并且每次只评估b”的神奇野兽。
【解决方案2】:

替代方法

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{

    int a[4][5] =
    {
       {1,1,0,1,0},
       {0,0,0,0,0},
       {0,1,0,0,0},
       {1,0,1,1,0}
    };

    int len = sizeof(a)/sizeof(a[0][0]) ;
    int * ptr = &a[0][0] ;
    while(len--)
    {
        printf("%d ", *ptr++);
    }
  
    return 0;
    
}

【讨论】:

    【解决方案3】:

    在这个for循环中

    for (; ptr < ptr+19; ptr++)
    

    表达式ptr的值总是小于表达式ptr + 19的值(前提是最后一个表达式没有溢出)。此外,指针ptr 在循环的每次迭代后都会递增。

    因此,使用此循环,您将可以访问数组 a 之外的内存,这会导致未定义的行为。

    你需要的是下面的for语句

    for ( ; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++)
    

    这是一个演示程序。

    #include <stdio.h>
    
    int main(void) 
    {
        int a[4][5] =
        {
           {1,1,0,1,0},
           {0,0,0,0,0},
           {0,1,0,0,0},
           {1,0,1,1,0}
        };
    
        for ( int *ptr = ( int * )a; ptr < ( int * )a + sizeof( a ) / sizeof( **a ); ptr++ )
        {
            printf( "%d ", *ptr );
        }
        
        putchar( '\n' );
        
        return 0;
    }
    

    程序输出是

    1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0
    

    【讨论】:

    • 我有一个问题,每次评估条件ptr &lt; ptr+19 是否将19 添加到ptr
    • @programmer29874 ptr 在 for 循环 ptr++ 的第三个表达式中递增。在 for 循环的第二个表达式(条件)中,比较了两个表达式 ptr 和 ptr + 19。
    猜你喜欢
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2016-01-20
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    相关资源
    最近更新 更多