【问题标题】:Using pointers to matrices in a scanf function在 scanf 函数中使用指向矩阵的指针
【发布时间】:2017-05-04 20:57:30
【问题描述】:

我在使用 scanf 输入矩阵时玩弄指针,出于某种原因,当我运行此代码时,只有每行的第一个元素被正确存储。

#include "stdio.h"

void main()
{
    int i, j, n, A[10][10];
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        for (j = 0; j < n; j++)
            scanf("%d", A + j + i*10);
}

这是我将 1,2,3,4,5,6,7,9 输入 3x3 矩阵并打印后得到的结果:

1 -858993460 -858993460

2 -858993460 -858993460

3 -858993460 -858993460

根据我对矩阵存储方式的理解,这应该可以。谁能指出我的代码有什么问题?

【问题讨论】:

  • A + j + i*10 是错误的。改成喜欢(int*)A + j + i*10
  • A + j + i*10 --> *(A + i) + j
  • 所以我需要将其转换为指针?为什么在将这个原理用于一维数组时我不必这样做?它只适用于 A + i 或其他东西。
  • 因为A作为表达式求值时的类型是int (*)[10],而不是int*
  • 错误的指针数学。 scanf("%d", A + j + i*10); --> scanf("%d", &amp;A[i][j]);

标签: c pointers memory matrix scanf


【解决方案1】:

您将A 声明为

int A[10][10];

也就是说,一个由 10 个数组组成的数组,每个数组有 10 个 ints。因此,当A 衰减为指向其第一个元素的指针时,该指针的类型为int (*)[10]。这是指向 10 个 ints 数组的指针,而不是指向单个 int 的指针。不同之处在于它们与指针算法的交互。因为指针算术是根据指向类型的大小定义的,所以只要i 不为零,表达式A + j + i*10 就会在数组A 的边界之外生成一个指针(指向10 个ints 的数组) .

最安全的方式是使用数组语法来选择数组元素:

&A[i][j]

。使用指针算法的类型正确替代方法包括

&(*(A + i))[j]

*(A + i) + j

后两者都依赖于表达式A + i 是指向int 数组的指针;取消引用该指针会生成一个数组,该数组可以是 [] 运算符的操作数(以及随后获取的结果地址)。或者,由*(A + i) 指定的数组在它作为+ 运算符的操作数出现时衰减到指向其第一个元素的指针(即衰减到int *),并将j 添加到它会产生指向数组*(A + i)jth 元素(与A[i] 指定的数组相同)。

【讨论】:

  • 哦,有道理。有一件事仍然困扰着我。当您使用 *(A + i) 时,您会得到一个数组。但是当你尊重它并且它是+ 运算符的操作数时,你会得到一个指向它的第一个元素的指针。对吗?
  • 是的,表达式*(A + i) 指定一个数组。就像任何其他数组一样,当该数组被评估为+(或大多数其他运算符)的操作数时,它会自动转换(“衰减”)为指向其第一个元素的指针。数组不会衰减为指针的情况很少。
【解决方案2】:

错误的指针数学。

A + j + i * 10

AA + j + i*10中使用时,它成为指向其第一个元素的指针,该元素是一个由10个int组成的数组。添加到A 的每个1 都会将其地址偏移40 个字节。

建议改用&amp;A[i][j]

代码重新设计以显示使用的地址。

#include "stdio.h"

int main() {
  int i, j, n, A[10][10];
  n = 3;
  char *base = (char*) A;
  for (i = 0; i < n; i++)
    for (j = 0; j < n; j++) {
      char *offset0 = (char*) (&A[i][j]);
      char *offset1 = (char *) (A + j + i * 10);
      printf("%d %d %3td %3td\n", i, j, offset0 - base, offset1 - base);
    }
}

输出

0 0   0   0
0 1   4  40
0 2   8  80
1 0  40 400
1 1  44 440
1 2  48 480
2 0  80 800
2 1  84 840
2 2  88 880

【讨论】:

    猜你喜欢
    • 2020-06-30
    • 2013-01-05
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多