【问题标题】:Matrix Access Ansi C矩阵访问 Ansi C
【发布时间】:2012-02-06 19:58:15
【问题描述】:

为什么 main 函数中的最后一个 printf 没有将值 10 打印到屏幕上? 我知道在ANSI C中,静态分配的矩阵以这种方式排列在内存中: 矩阵:矩阵[0][0]、矩阵[0][1]、...、矩阵[0][ColumnsDimension-1]、矩阵[1][0]等

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

#define dimRighe 20
#define dimColonne 30

int main()
{
    int matrice[dimRighe][dimColonne]; 
    int i,j;
    for(i=0;i<dimRighe;i++)
        for(j=0;j<dimColonne;j++)
            matrice[i][j] = i+j; 
    matrice[0][3] = 10; 
    i = 0; j = 3;
    printf("%d",*matrice[i*dimColonne+j]); 
    return 0;
}

【问题讨论】:

  • 为什么不直接使用matrice[i*dimCollonne][j]
  • @ChrisBrowne 那也是错误的。你的意思是说matrice[i][j]

标签: c matrix ansi


【解决方案1】:

请改用*(matrice[i * dimColonne] + j)

【讨论】:

  • 谢谢!我不明白一件事:为什么必须对矩阵进行两次解引用?它不仅仅是一个包含我的矩阵元素的大数组?
  • 你写matrice[0][3]以避免犯这样的错误!不要试图自己计算出这些偏移量。让编译器完成繁重的工作。它不会出错。你会的。
  • @MasterChief matriceint 的数组。 matrice 的值是指向int 的数组dimColonne 的指针。因此,要访问 int 元素,需要两个取消引用:通过 *[] 运算符。
【解决方案2】:

为什么 main 函数中的最后一个 printf 没有将值 10 打印到屏幕上?

因为matrice 是一个数组数组...
matrice[whatever] 是一个数组(在大多数情况下,它“衰减”为指向其第一个元素的指针)

*matrice[whatever]是数组matrice[whatever]的第一个元素的内容。

【讨论】:

    【解决方案3】:

    在您的代码中:

    matrice[i*dimColonne+j]
    

    由于i0,因此计算结果为

    matrice[j]
    

    因为j3 这意味着

    matrice[3]
    

    当您打印*matrice[3] 时,这相当于打印matrice[3][0],因为matrice[3] 是一个数组。并且数组衰减为指向其第一个元素的指针。

    但你根本不想这样做。您应该简单地写matrice[i][j] 并让编译器完成工作。

    【讨论】:

      【解决方案4】:

      改变

      printf("%d",*matrice[i*dimColonne+j]);  
      

      简单地说

      printf("%d", matrice[i][j]);
      

      如果您所担心的只是打印出正确的值。毕竟,这就是你分配它的方式。

      如果您这样做是为了了解数组下标的工作原理,那么您需要记住几件事。

      首先,除非它是 sizeof 或一元 &amp; 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,类型为“@987654325 的 N 元素数组”的表达式@" 将替换为 ("decay to") 类型的表达式 "pointer to T",其值将是数组第一个元素的地址。表达式matrice 是一个类型为“int 的30 元素数组的20 元素数组”的数组表达式;在大多数情况下,它将被转换为“指向int 的30 元素数组的指针”或int (*)[30] 类型的表达式。同样,表达式matrice[i] 是“int 的30 元素数组”类型的表达式,在大多数情况下,它将转换为“指向int 的指针”或int * 类型的表达式。

      这是一张方便记住所有这些内容的表格:

      声明:Ta[N]; 表达式类型衰减到 ---------- ---- --------- 一个 T [N] T * &a T (*)[N] *在 一个[我] T 声明:Ta[M][N]; 表达式类型衰减到 ---------- ---- --------- 一个 T [M][N] T (*)[N] &a T (*)[M][N] *一个 T [N] T * a[i] T [N] T * &a[i] T (*)[N] *a[i] T a[i][j]T

      二、下标操作a[i]定义为*(a + i);也就是说,您根据数组的基地址中的i 元素 (NOT BYTES) 数计算地址并取消引用结果。例如,如果aint 的数组,那么*(a + i) 将在a 之后为您提供i'th 整数 的值。如果 an 是struct foo 的数组,那么*(a + i) 将在a 之后为您提供i'th struct 的值。指针算术总是考虑基本类型的大小,因此您无需担心偏移量中的字节数

      同样的逻辑也适用于多维数组,你只需对每个维度递归地应用规则:

          a[i][j] ==   *(a[i] + j) ==    *(*(a + i) + j)
       a[i][j][k] == *(a[i][j]+ k) == *(*(a[i] + j) + k) == *(*(*(a + i) + j) + k)  
      

      请注意,您应该几乎从不必须手动执行这些取消引用;编译器知道数组访问是什么样子,并可以相应地优化代码。在适当的情况下,手动写出取消引用可能会导致代码比使用下标运算符

      您可以像这样对二维数组进行索引,就像它是一维数组一样:

      a[i*rows + j] = val;
      

      但我不会(表达式的类型不完全匹配)。请注意,您将i 乘以行数,而不是列数。

      【讨论】:

        【解决方案5】:

        你也可以这样打印:

        char *matrixAsByteArray = (char *) matrice;
        char *startIntAddr = matrixAsByteArray + i * dimColonne * sizeof(int) + j * sizeof(int);
        
        int outInt = *startIntAddr | *(startIntAddr + 1) << 8 | *(startIntAddr + 2) << 16 | *(startIntAddr + 3) << 24;
        printf("%d", outInt);
        

        首先,它将矩阵转换为字节数组,然后获取所需整数的起始地址,然后从从该地址读取的前四个字节重构整数。

        这有点矫枉过正,但解决问题的方法很有趣。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-24
          • 2016-03-31
          • 2013-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多