矩阵存取Ansi C

6bc51xsx  于 2023-03-22  发布在  其他
关注(0)|答案(5)|浏览(129)

为什么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;
}
olmpazwi

olmpazwi1#

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

zour9fqk

zour9fqk2#

为什么main函数中的最后一个printf没有将值10打印到屏幕上?
因为matrice是一个数组的数组…
matrice[whatever]是一个数组(在大多数情况下,它会“衰减”为指向其第一个元素的指针)
*matrice[whatever]是数组matrice[whatever]的第一个元素的内容。

7vux5j2d

7vux5j2d3#

在您的代码中,您有:

matrice[i*dimColonne+j]

由于i0,因此计算结果为

matrice[j]

由于j3,这意味着

matrice[3]

当你打印*matrice[3]的时候,就相当于打印matrice[3][0],因为matrice[3]是一个数组,数组会衰减到指向它第一个元素的指针。
但是你根本不想这样做,你应该简单地写matrice[i][j],让编译器来完成这项工作。

n3h0vuf2

n3h0vuf24#

变更

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

简单地说

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

如果你所担心的只是打印出正确的值。毕竟,这就是你如何赋值的。
如果您是为了了解数组下标是如何工作的,那么有几件事需要记住。
首先,除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则类型为“T的N元素数组”的表达式将被替换为(“decay to”)类型为“pointer to T”的表达式,它的值将是数组第一个元素的地址。表达式matrice是类型为“30个元素的20个元素的数组”的数组表达式。int“的元素数组;在大多数情况下,它将被转换成类型为“指向int的30元素数组的指针”或int (*)[30]的表达式。类似地,表达式matrice[i]是类型为“指向int的30元素数组“的表达式,并且在大多数情况下,它将被转换成类型为“指向int的指针“或&的表达式。
这里有一个方便的表格来记住所有这些:

Declaration: T a[N];

Expression              Type              Decays to
----------              ----              ---------        
         a              T [N]             T *
        &a              T (*)[N]
        *a              T 
      a[i]              T

Declaration: T a[M][N];

Expression              Type              Decays to
----------              ----              ---------
         a              T [M][N]          T (*)[N]
        &a              T (*)[M][N]    
        *a              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个整数的值。如果an是struct foo的数组,那么*(a + i)将给予你a之后的第i个结构体的值。指针算法总是考虑基类型的大小,所以你不需要担心偏移量中的 * 字节数 *。
同样的逻辑也适用于多维数组,你只需要对每个维度递归地应用规则:

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乘以 * 行数 *,而不是列数。

inn6fuwd

inn6fuwd5#

你也可以这样打印:

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);

首先,它将矩阵转换为字节数组,然后,它获取所需整数的起始地址,然后从该地址读取的前四个字节重建整数。
这是一个有点矫枉过正,但有趣的解决方案的问题。

相关问题