【问题标题】:Passing pointer to multidimensional array as arguments将指向多维数组的指针作为参数传递
【发布时间】:2019-04-12 01:08:42
【问题描述】:

我是初学者,正在尝试了解多维数组的工作原理

请看这段代码:

#include<stdio.h>

void getData(int c;int *a,int r,int c)
{
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            scanf("%d",(*(a+i)+j)); //warning 
    return;
}

void putData(int c;int *a,int r,int c)
{
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            printf("%d",*(*(a+i)+j));  //error
    printf("\n");
}

int main(void)
{
    int r1,r2,c1,c2;
    printf("Enter order of A:\n");
    scanf("%d %d",&r1,&c1);
    printf("Enter order of B:\n");
    scanf("%d %d",&r2,&c2);
    int a[r1][c1],b[r2][c2];
    getData((int *)a,r1,c1);
    getData((int *)b,r2,c2);
    putData((int *)b,r2,c2);
}

我无法理解指针如何传递给函数以及错误的原因。但我想如果我能理解指针是如何工作的,那么我可能能够调试它。 请帮忙!谢谢!

编辑:我真的很想了解指针如何与寻址和东西一起工作。因此,如果有某种追踪,它可能会对我有所帮助

【问题讨论】:

  • 索引一维数组时,函数知道如何根据数据类型索引数组。例如,当您使用整数时,假设一个整数在传递数组时占用 4 个字节(取决于机器),您将指针传递给数组中的第一个元素,然后函数可以通过递增指针来找到 arr[1]按整数的大小,例如 4 个字节。想想如果函数是 2D 数组并且您尝试访问 arr[0][1] 函数可能需要什么额外信息
  • 所以应该是*(*(a*i)+j)
  • 很遗憾我现在没有时间。希望有人会帮助,如果没有,我明天会回来。我会查找诸如“如何将 2D 数组传递给函数”之类的内容。
  • void getData(int c;int *a,int r,int c) 是语法错误

标签: c pointers multidimensional-array


【解决方案1】:

当您将 VLA 作为参数(或任何二维数组)传递时,您必须至少传递每行的元素数,以便您可以为您的 VLA(二维数组)声明一个完整的类型。

虽然你可以通过:

void getData (int r, int c, int a[r][c])

你也可以通过:

void getData (int r, int c, int (*a)[c])

(由于第一级间接转换为指针,请参阅:C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) -- 并注意异常)

c 必须包含在参数列表中之前 a 否则a 的类型将不完整,因为c 尚未定义。

虽然您可以将*(*(a + i) + j) 写成a[i][j] 的等效指针表示法——不要,它的可读性较差(但完全等效)。

始终、始终、始终验证每个输入。否则,您可能会在 inputmatching 失败后调用 Undefined Behavior scanf,例如

    printf("Enter order of A:\n");
    if (scanf ("%d %d", &r1, &c1) != 2) {   /* validate EVERY input */
        fputs ("error: invalid input (r1, c1).\n", stderr);
        return 1;
    }

总而言之,你可以这样做:

#include <stdio.h>
#include <stdlib.h> /* for EXIT_FAILURE */

void getData (int r, int c, int (*a)[c])
{
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            if (scanf ("%d", &a[i][j]) != 1) {
                fputs ("error: invalid input a[i][j].\n", stderr);
                exit (EXIT_FAILURE);
            }
}

void putData (int r, int c, int (*a)[c])
{
    for (int i = 0; i < r; i++) {
        for(int j = 0; j < c; j++)
            printf (" %2d", a[i][j]);   /* more readable */
            /* printf (" %2d", *(*(a + i) + j)); */
        putchar ('\n');  /* use putchar for a single char, instead of printf */
    }
}

int main(void)
{
    int r1, r2, c1, c2;

    printf ("Enter order of A:\n");
    if (scanf ("%d %d", &r1, &c1) != 2) {   /* validate EVERY input */
        fputs ("error: invalid input (r1, c1).\n", stderr);
        return 1;
    }

    printf ("Enter order of B:\n");
    if (scanf ("%d %d", &r2, &c2) != 2) {   /* validate EVERY input */
        fputs ("error: invalid input (r2, c2).\n", stderr);
        return 1;
    }
    int a[r1][c1], b[r2][c2];

    getData (r1, c1, a);
    getData (r2, c2, b);

    puts ("a");
    putData (r1, c1, a);
    puts ("\nb");
    putData (r2, c2, b);
}

注意:stdlib.h 包含在EXIT_FAILURE 宏中,并注意代码中的额外间距——对老年人有帮助)

使用/输出示例

$ echo "2 3 2 3 1 2 3 4 5 6 7 8 9 10 11 12" | ./bin/scanfvla
Enter order of A:
Enter order of B:
a
  1  2  3
  4  5  6

b
  7  8  9
 10 11 12

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    相关资源
    最近更新 更多