在 C 中打印多维数组

Printing a multidimensional array in C

我正在尝试使用指针在 C 中打印二维数组,但没有得到预期的输出。

程序:-

#include <stdio.h>
int main()
{
    int arr[2][3] = {{1,2,3},{4,5,6}};
    int* p;
    for ( p = arr; p <= arr+6; p++)
    {
        printf("%d ", *p);
    }
    return 0;
}

输出:-

1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463

你能告诉我哪里错了吗,因为输出应该只是:

1 2 3 4 5 6

在极少数情况下,表达式中使用的数组指示符会隐式转换为指向其第一个元素的指针。

这个数组的数组元素的类型

int arr[2][3];

int [3]。因此,指向数组第一个元素的指针的类型为 int ( * )[3].

这个作业

p = arr;

其中 p 的类型 int * 不正确,因为赋值的操作数具有不兼容的指针类型。

至少你需要将正确的表达式转换为类型int * like

p = ( int * )arr;

您需要在 for 循环的条件中使用相同的转换。那不是

p <= arr+6

你必须写

p < ( int * )arr+6

下面有一个演示程序,展示了如何使用指针将 two-dimensional 数组输出为 two-dimensional 数组。

#include <stdio.h>

int main( void )
{
    int arr[2][3] = {{1,2,3},{4,5,6}};

    for ( int ( *p )[3] = arr; p != arr + 2; p++ )
    {
        for ( int *q = *p; q != *p + 3; ++q )
        {
            printf( "%d ", *q );
        }
        putchar( '\n' );
    }

    return 0;
}

如果你想将 two-dimensional 数组输出为 one-dimensional 数组,那么你可以写

#include <stdio.h>

int main( void )
{
    int arr[2][3] = {{1,2,3},{4,5,6}};

    for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
    {
        printf( "%d ", *p );
    }
    putchar( '\n' );

    return 0;
}

Could you tell me where I am wrong

arr的元素不是整数,而是3个整数的数组。所以 arr+6 肯定是一个与您期望的地址不同的地址,因为指针算法以数组中类型大小的倍数计算。

最好使用嵌套循环遍历多维数组;将其视为 int 的一个 single-dimensional 数组会导致您在此处看到的那种混乱。代码更难理解和验证,不会慢。

首先,当循环遍历大小为 n 且索引为 i 的数组时,继续的条件应该是 i < n 而不是 i <= n,因为数组索引在C 运行 从 0n-1.

但是,您的代码有一个更严重的错误:一维数组可以'decayed'变成指向元素类型的指针;但是,二维数组会衰减为 指向一维数组的指针 。因此,在您的情况下, type 表达式中使用的指针 arr + 6 是指向三个整数数组的指针;此外,当添加 6 时,该操作是根据 pointed-to 对象的大小执行的,即 sizeof(int) * 3 – 因此,即使将 <= 更改为<,您将 运行ning 远远超出数组的实际范围。

要使指针算法在正确的 'units' 中工作(即 sizeof(int)),请将 arr 转换为 int* before 添加(同时将 <= 更改为 <):

#include <stdio.h>
int main()
{
    int arr[2][3] = { {1,2,3},{4,5,6} };
    int* p;
    for (p = (int*)arr; p < (int*)arr + 6; p++) {
        printf("%d ", *p);
    }
    return 0;
}

您试图以错误的方式访问值,two-dimensional 数组在内存中保存为连续块。因此,如果我们将 ptr 的值增加 1,我们将移动到分配内存中的下一个块。

int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;

int i,j;
for (i = 0; i < 6; i++) {
    printf("%d ", *(ptr + i));
}
return 0;

    for ( p = arr; p <= arr+6; p++)

作为右值的表达式arr是一个指向数组第一个元素的指针(即属于 int [3] 类型,因此每次您增加该指针时,它都会向前移动三个 int 位置 --- 整行 --- 因此,在第六行之后 arr + 6 点数组的(如果数组应该有六行)你可以用表达式 arr + 2 这是第二行之后的第一个数组元素的地址(以及数组的行数)。

你也可以声明

    int (*aux)[2][3] = &arr;  /* aux is a pointer to the whole 3x2 array,
                        * so aux + 1 will be the position of the second
                        * 2D array after this one */

然后

    int *end = (int *)(aux + 1);

或者干脆

    int *end = (int *)(&arr + 1); /* see below */

(注意arr&arr都是指针,指向同一个地方,但不是同一个类型(arrint (*)[3]类型&arr 的类型是 int(*)[2][3])

所以让我们将您的代码重写为

    for (p = (int *)arr; p < end; p++)

    for (p = (int *)arr; p < (int *)&arr + 1; p++)

会起作用,在完整的数组单元中进行微积分比在行或单个单元格中进行微积分似乎更自然(并且您可以自由更改数组的维度)

您的代码将是:

#include <stdio.h>
int main()
{
    int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
    int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop 
                                   * despite that it can be optimized to comparing
                                   * with a constant value */
    char *sep = "";
    for (int *p = (int *)arr; p < end; p++)
    {
        printf("%s%d", sep, *p);
        sep = ", ";
    }
    putchar('\n');
    return 0;
}

(请注意,您必须使用 < 运算符而不是 <=,因为您不想打印 end 指向的值,因为它位于数组)

最后一个注意事项:这将适用于真正的数组,但不适用于声明为数组的函数参数,因为它们衰减为指针然后 &arr 不是指向数据数组大小的指针,而是参数本身的地址,它指向其他地方的数组。