【问题标题】:Matrix, pointers, C*矩阵、指针、C*
【发布时间】:2016-01-06 21:21:44
【问题描述】:

我有这样的代码:

void print_matrix(int **a, int n) {
    int i, j;
    for(i = 0; i < n; i++) {
        for(j = 0; j < n; j++)
            printf("%d\t", *(a+i*n+j));
        putchar('\n');
    }
}

int main () {
  int matrix[3][3];

  insert (matrix); /* Function that reads Matrix from stdin */
  print_matrix(matrix, 3);
  return 1; 
}

我收到 GCC 错误:

预期为“int **”,但参数类型为“int (*)[3]”

我阅读了所有相关主题,但仍然找不到问题的答案,所以在将其标记为重复之前,请阅读它。

指针不是数组,我明白这一点。我在某处读到元素不是连续的,在这种情况下,这可能会发生:111 222 333 -> 111 是第一个 int 数组的地址,222 是第二个 int 数组的地址,333 是第三个 int 数组的地址。但如果是这样的话,我不明白为什么 GCC 会给我一个错误。

首先,我希望有人能证实我所读到的内容是真实的。如果有人能给我答案,我将不胜感激。

请注意,我知道 *(a+i*n+j) 是不正确的,以防矩阵的内存不是连续的。

最好的问候。

【问题讨论】:

  • 类型不等价,int [3][3] 是 9 个整数的连续存储,而int ** 是指向(可能是指针数组)指针的指针。跨度>
  • 你能告诉我有什么可能的解决办法吗?
  • 但是你解引用错了,你能写a[j][i]吗?
  • 我明白为什么它现在不起作用了,但我不知道除了 print_matrix(int a[][3], int n) 之外还有什么可能的修复方法。

标签: c pointers matrix


【解决方案1】:

当您传递int[3][3] 时,该函数会收到一个指向(int*)[3] 的指针,它是一个指向3 个整数数组的指针。因为当您将数组传递给函数时,它会转换为指向其第一个元素的指针。

所以相应地调整功能。一种方法是将其作为指向数组的指针接收。你的数组索引也是错误的。您可以像索引真实数组一样索引。

void print_matrix(int (*a)[3], int n) {

    int i, j;
    for(i = 0; i < n; i++) {
        for(j = 0; j < n; j++)
            printf("%d\t", a[i][j]);
        putchar('\n');
    }

}

如果你使用 C99,你可以通过两个维度:

void print_matrix(int x, int y, int a[x][y]) {

    int i, j;
    for(i = 0; i < x; i++) {
        for(j = 0; j < y; j++)
            printf("%d\t", a[i][j]);
        putchar('\n');
    }

}

并将其称为:

  print_matrix(3, 3, matrix);

只是为了说明您将如何访问各个“数组”:

void print_matrix(int (*a)[3], int n) {
    int i, j;
    for(i = 0; i < n; i++) {
       int *p = a+i;
        for(j = 0; j < 3; j++)
            printf("%d\t", p[j]);
        putchar('\n');
    }

}

【讨论】:

  • 当你传递 int[3][3] 时,函数接收到一个指向 (int*)[3] 的指针,它是一个指向 3 个 int 数组的指针。因为当您将数组传递给函数时,它会转换为指向其第一个元素的指针。 - 你能再解释一下吗?
  • 在 C 中,您既不能将 array 传递给函数也不能从函数返回。它总是被转换成指向它的第一个元素的指针。所以数组丢失了它的大小信息,变成了一个指针(在函数内部),这也是你不能在它上面使用sizeof 来获取它的实际大小的原因。请参阅专门涵盖此主题的 What is array decaying?
  • 所以基本上当我传递给函数 int[3][3] 时,只有第一个 int[3] 转换为指针,然后我得到 (int*)[3] 这就是指向3 个整数的数组,而不是 3 个指向 3 个不同数组的指针?
  • 是的。但是指针仍然指向同一个数组。这就是为什么你可以像一个真正的数组一样索引它或增加它以获得接下来的 3 个整数。如果您有 1D arrat,则:int a[3]; func(a); void func(int *a) {..}。如果你有一个二维数组,那么:int a[3][3]; func(a); void func(int (*a)[3]) {..} 等等。
  • @АлександарМакрагић 我刚刚编辑了可能会增加一点清晰度。
【解决方案2】:

如果你想让 n 变化(并且是平方),最好分配和使用一个单维数组,当你想要不同的行时乘以。

int matrix[3*3];

怎么用?

matrix[row*3+col] = 5;

如何通过。

f(int *a,int n)

【讨论】:

    【解决方案3】:

    int** 是一个指向指针的指针(指向一个 int)。

    int[3][3],作为函数参数,被转换为指向int 数组的指针 - 参见Is an array name a pointer?

    所以类型不匹配,正如编译器告诉你的那样。

    注意:如果您在函数中进行指针运算,则可以传递 int *a 而不是 int **a(通过强制转换:print_matrix((int *)matrix, 3);。这很难看,但有助于理解发生了什么 - 即 @987654328 @ 数组完全作为int[9] 数组存储在内存中,如果您自己计算int 位置,就像您一样,它也可以作为一维数组工作。

    【讨论】:

    • int[3][3] 是一个数组数组。没有“作为指针”,因为它不是一个。这可能是一个术语问题,但我认为正确处理这一点很重要,因为它让很多初学者(以及一些非初学者)感到困惑
    • 作为参数,int[3][3]确实被转换为指针。但你是对的,我会更新描述,不太清楚。事实上,我将参数变量的实际内容与编译器“看到”的类型混合在一起。
    • 是的,我想如果你解释一下T[42] 类型的参数被调整为T* 那就更清楚了。但是,问题中没有int[N][N] 类型的参数。只有一个论点。
    • @juanchopanza done (注意参数我的意思是函数参数)
    猜你喜欢
    • 1970-01-01
    • 2017-04-05
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多