5

我以两种不同的方式在 C 中创建了两个二维数组(矩阵)。
我不明白它们在内存中的表示方式之间的区别,以及我不能以相同方式引用它们的原因:

scanf("%d", &intMatrix1[i][j]); //can't refer as  &intMatrix1[(i * lines)+j])

scanf("%d", &intMatrix2[(i * lines)+j]); //can't refer as &intMatrix2[i][j])

这两个数组的实现方式有什么区别,为什么我必须以不同的方式引用它们?

如何以相同的方式(??????在我的printMatrix函数中)引用每个数组中的元素?

int main()
{
   int **intMatrix1;
   int *intMatrix2;

   int i, j, lines, columns;

   lines = 3;
   columns = 2;

   /************************* intMatrix1 ****************************/

   intMatrix1 = (int **)malloc(lines * sizeof(int *));

   for (i = 0; i < lines; ++i)
      intMatrix1[i] = (int *)malloc(columns * sizeof(int));

   for (i = 0; i < lines; ++i)
   {
       for (j = 0; j < columns; ++j)
       {
       printf("Type a number for intMatrix1[%d][%d]\t", i, j);
       scanf("%d", &intMatrix1[i][j]); 
       }
   }

   /************************* intMatrix2 ****************************/ 

   intMatrix2 = (int *)malloc(lines * columns * sizeof(int));

   for (i = 0; i < lines; ++i)
   {
       for (j = 0; j < columns; ++j)
       {
       printf("Type a number for intMatrix2[%d][%d]\t", i, j);
       scanf("%d", &intMatrix2[(i * lines)+j]);
       }
   }

   /************** printing intMatrix1 & intMatrix2 ****************/

   printf("intMatrix1:\n\n");
   printMatrix(*intMatrix1, lines, columns);

   printf("intMatrix2:\n\n");
   printMatrix(intMatrix2, lines, columns);
}


/************************* printMatrix ****************************/

void printMatrix(int *ptArray, int h, int w)
{
    int i, j;

    printf("Printing matrix...\n\n\n");

    for (i = 0; i < h; ++i)
        for (j = 0; j < w; ++j)
        printf("array[%d][%d] ==============> %d\n, i, j, ??????);
}
4

4 回答 4

5

您正在取消引用Matrix1两次..

Matrix1[i][j] ;

这意味着它是一个二维数组或这样声明的双指针。

int **Matrix1 ;

Adouble pointer可以被认为是指针数组。它的每个元素本身就是一个指针,因此它被取消引用一次以到达指针元素,并取消引用两次以访问该成员指针或数组的数据成员。你写的这个声明相当于这个..

Matrix1[i][j] ;   //is ~ to

*( *(Matrix1 + i) + j) ;

对于这样的单个指针。

int *Matrix2 ;

您只能取消引用一次,就像这样。

Matrix2[i] ;  //is ~ to
*(Matrix2 + i) ;

你写的这个声明..

Matrix2[(i * lines)+j] ;
         |-----------|

这部分计算为一个数字,因此它取消了一次。

(i * lines) + j ;

至于您的printmatrix()函数,ptArray传递给它的是单个指针。所以你不能取消引用它两次。

也许您可以从我在这里的回答中更好地理解静态和动态二维数组。

二维数组作为函数的参数

于 2012-10-08T15:21:14.363 回答
3

两个矩阵都是内存中的字节序列。但是,它们之间的区别在于您如何定义内存接口来表示矩阵。在一种情况下,您只是定义一个内存段,其元素数量等于矩阵中的元素,而在另一种情况下,您专门分配内存来表示每个特定的行。

以下情况的计算成本更高,因为您调用malloc()的次数更多:

intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
  intMatrix1[i] = (int *)malloc(columns * sizeof(int));

但是,它带来的优势是您可以更清晰地引用矩阵元素:

intMatrix1[i][j];

如果您只分配一个元素序列等于矩阵中的元素数量,则必须考虑行/列索引计算以引用内存中的正确矩阵元素。

为了尝试增加代码的一致性程度,我可以建议一个接收矩阵行引用和矩阵列数并打印一行的函数吗?

void PrintLine(int *ptrLine, int lineLen) {
   unsigned int i;
   for(i = 0; i < lineLen; i++)
      printf("%d ", ptrLine[i]);
   printf("\n");
}

然后,对于每种矩阵类型,您只需执行以下操作:

// Case 1
for(i = 0; i < lines; i++)
   PrintLine(intMatrix1[i], columns);
// Case 2
for(i = 0; i < lines; i++) {
   PrintLine(intMatrix2 + i*columns, columns);
}
于 2012-10-08T15:22:41.880 回答
2

在 C 中,数组访问运算符[]实际上只是一种执行指针运算的更简洁的方法。对于类型为 的元素的一维数组type_sarr[i]等价于*(arr + (i * sizeof(type_s)))。要剖析该表达式:

  • arr将是基地址,即存储此数组的最低内存地址
  • i是数组中元素的零索引位置
  • sizeof返回元素 in占用内存的chars 数(通常与字节数相同,但 C 规范没有强制要求) 。arr编译器将确定元素的大小并为您执行此数学运算。

作为旁注,此语法具有arr[i]等效于的副作用i[arr],尽管普遍接受将索引放在括号中。

综上所述,让我们看看您的两个声明之间的区别:

intMatrix1[i][j]相当于*(*(intMatrix1 + i * sizeof(int)) + j * sizeof(int))。因此,该表达式中有两个取消引用运算符,这意味着 intMatrix 是一个数组数组(它包含指向指针的指针)。

另一方面,intMatrix2[(i * lines)+j]等价于*(intMatrix2 + ((i * lines) + j) * sizeof(int)),它只包含一个解引用运算符。您在这里所做的是定义一个包含与原始二维数组相同数量的元素的一维数组。如果您的数据可以最好地用矩阵表示,那么我建议您使用第一个版本:intMatrix1[i][j].

于 2012-10-08T15:24:23.213 回答
2

不同之处在于第一个数组:

intMatrix1 = (int **)malloc(lines * sizeof(int *));

创建一个指针数组intMatrix1。这些指针中的每一个都指向一个 int 数组(你在这里 malloc )。

for (i = 0; i < lines; ++i)
   intMatrix1[i] = (int *)malloc(columns * sizeof(int));

这就是为什么您需要声明中的 2 星(取消对指针数组的引用,然后是对 int 数组的引用)和双括号来访问单个元素:

int **intMatrix1;

int i = intMatrix[row][column];
int i = *(*(intmatrix + row) + column);

对于第二个矩阵,您只创建一个大小为 column * rows 的 int 数组。

int *intMatrix2 = (int *)malloc(lines * columns * sizeof(int));

int i = intMatrix[row + column];
int i = *(intMatrix + row + column);

要打印 2 个数组,您必须使用不同的打印函数,因为 2 个矩阵的内部结构不同,但您已经知道访问这两个数组的不同方法。

于 2012-10-08T15:21:23.747 回答