简体   繁体   English

带指针的 C 中的矩阵加法

[英]Matrix Addition in C with pointers

I am trying to add 2 matrices with pointers but only the first row is being computed properly.我试图用指针添加 2 个矩阵,但只有第一行被正确计算。 The second row, only row-1 computations are done.第二行,只完成第 1 行的计算。 the rest of the matrix is just 0. I have tried malloc but then the entire resultant matrix is just 0.矩阵的其余部分仅为 0。我尝试过 malloc,但整个结果矩阵仅为 0。

Clarification : I have a working code for [i][j] method.说明:我有 [i][j] 方法的工作代码。 However, I wanted to implement the same using pointers but unable to.但是,我想使用指针实现相同的功能,但无法实现。


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define rng 10

int main (void)
{
    int selection,row,column,i,j;

    //Initial statements, input method selection and matrix dimension inputs
    printf("\n\tThis program performs addition of 2 matrices.");
    printf("\n\n\tThe matrix elements can be fed through a Random Number Generator or be fed by the user.");
    printf("\n\tPress 1 to initialise array with RNG values.");
    printf("\n\tPress 2 to initialise array with user fed values.");
    printf("\n\tSelection : ");
    scanf("%d",&selection);
    if(((selection==1)||(selection==2))==0)
    {
        printf("\n\tPlease make a valid selection next time. Closing GUI.\n");
        exit (0);
    }

    printf("\n\tPlease enter the matrix dimensions.\n");
    printf("\tPlease enter the number of rows : ");
    scanf("%d",&row);
    printf("\tPlease enter the number of columns : ");
    scanf("%d",&column);
    if(((row==0)||(column==0))==1)
    {
        printf("\n\tInvalid matrix dimensions. Closing GUI.\n");
        exit (0);
    }
    int matrix_1[row][column];
    int matrix_2[row][column];
    int matrix_3[row][column];              //Resultant Matrix

    //Matrix initialisation
    if(selection==1)
    {
        printf("\n\tA matrix with RNG values between 1 and %d will be generated.",rng);
        srand(time(NULL));
        for(i=0;i<row;i++)
        {
            for (j=0;j<column;j++)
            {
                matrix_1[i][j]=1+rand()%rng;
                matrix_2[i][j]=1+rand()%rng;
            }
        }
    }
    else
    {
        printf("\n\tPlease enter the matrix values.\n");
        printf("\n\tMatrix 1 : \n");
        for(i=0;i<row;i++)
        {
            for (j=0;j<column;j++)
            {
               printf("\tMatrix 1 [%d][%d] : ",i,j);
               scanf("%d",&matrix_1[i][j]);
            }
            printf("\n");
        }

        printf("\n\tMatrix 2 : \n");
        for(i=0;i<row;i++)
        {
            for (j=0;j<column;j++)
            {
               printf("\tMatrix 2 [%d][%d] : ",i,j);
               scanf("%d",&matrix_2[i][j]);
            }
            printf("\n");
        }
    }

    //Initialise matrix_3 aka resultant matrix
    for(i=0;i<row;i++)
        for (j=0;j<column;j++)
            matrix_3[i][j]=0;


    //Print the Matrices
    printf("\n\tMatrix 1 is : \n");
    for(i=0;i<row;i++)
    {
        for (j=0;j<column;j++)
        {
            printf("\t%d",matrix_1[i][j]);
        }
        printf("\n");
    }
    printf("\n\tMatrix 2 is : \n");
    for(i=0;i<row;i++)
    {
        for (j=0;j<column;j++)
        {
            printf("\t%d",matrix_2[i][j]);
        }
        printf("\n");
    }

    //Add the matrices
    int *loc_1=&matrix_1[0][0];
    int *loc_2=&matrix_2[0][0];
    int *loc_3=&matrix_3[0][0];

    for(i=0;i<row;i++)
    {
        for(j=0;j<column;j++)
        {
            *(loc_3+i+j) = *(loc_1+i+j) + *(loc_2+i+j);
        }
    }

    //Print the resultant matrix
    printf("\n\tThe resultant matrix after addition is : \n");
    for(i=0;i<row;i++)
    {
        for (j=0;j<column;j++)
        {
            printf("\t%d",matrix_3[i][j]);
        }
        printf("\n");
    }

}

The output is like this :输出是这样的:

val1 val2 val3 val4
val5 val6 val7 0
0     0    0   0
0     0    0   0

Matrix adding code is incorrect:矩阵添加代码不正确:

    int *loc_1=&matrix_1[0][0];
    int *loc_2=&matrix_2[0][0];
    int *loc_3=&matrix_3[0][0];

    for(i=0;i<row;i++)
    {
        for(j=0;j<column;j++)
        {
            *(loc_3+i+j) = *(loc_1+i+j) + *(loc_2+i+j);
        }
    }

Operation *(loc_1 + i + j) is more or less equivalent to matrix_1[0][i + j] .操作*(loc_1 + i + j)或多或少等价于matrix_1[0][i + j] See following derivation见以下推导

*(loc_1 + i + j)                // loc_1 == &matrix[0][0]
*(&matrix[0][0] + i + j)        // matrix[0][0] == *(matrix[0] + 0)
*(&*(matrix[0] + 0) + i + j)    // &* cancel out
*(matrix[0] + 0 + i + j)
*(matrix[0] + i + j)
matrix[0][i + j]

Operation matrix_1[0][i + j] is incorrect because:操作matrix_1[0][i + j]不正确,因为:

  • it returns difference value from matrix_1[i][j]它从matrix_1[i][j]返回差值
  • invokes Undefined Behavior when i + j >= columnsi + j >= columns时调用未定义行为

I assume that you have some very good reason to introduce loc_<n> variables rather than using matrix_<n> .我假设您有一些很好的理由来引入loc_<n>变量而不是使用matrix_<n>

It should be:它应该是:

int (*loc_1)[column] = matrix_1;
int (*loc_2)[column] = matrix_2;
int (*loc_3)[column] = matrix_3;

    for(i=0;i<row;i++)
    {
        for(j=0;j<column;j++)
        {
            loc_3[i][j] = loc_1[i][j] + loc_2[i][j];
        }
    }

Array matrix_1 of type int[row][column] decays to a pointer to its first element which is int[colums] . int[row][column]类型的数组matrix_1衰减为指向其第一个元素int[colums]的指针。 Therefore the expression matrix_1 can be assigned to a variable of type int(*)[column] .因此,表达式matrix_1可以分配给int(*)[column]类型的变量。

Your code is attempting to access the 2D array (aka array of array) using a pointer to the first element of the 2D array.您的代码正在尝试使用指向二维数组第一个元素的指针访问二维数组(又名数组数组)。 That is not standard compliant .不符合标准 Once i+j is greater than or equal to column your code is illegal according to the standard.一旦i+j大于或等于column根据标准,您的代码就是非法的。

However, on most systems it will work despite not being strictly standard compliant.然而,在大多数系统上,尽管不严格符合标准,它仍然可以工作。 But you have to multiply i with column to get the correct indexing.但是您必须将icolumn相乘才能获得正确的索引。 Like:喜欢:

// NOT STANDARD COMPLIANT (but will work on most systems). NOT RECOMMENDED
*(loc_3+i*column+j) = *(loc_1+i*column+j) + *(loc_2+i*column+j);

But why do something which isn't standard compliant when you can do it much simpler with compliant code?但是,当您可以使用兼容代码更简单地做一些不符合标准的事情时,为什么还要做一些不符合标准的事情呢? Just do:做就是了:

matrix_3[i][j] = matrix_1[i][j] + matrix_2[i][j];

It's simple, compliant and doesn't require any extra variables.它简单、合规并且不需要任何额外的变量。

It can also be written也可以这样写

*(*(matrix_3 + i) + j) = *(*(matrix_1 + i) + j) + *(*(matrix_2 + i) + j);

but that's just making the code harder to read.但这只会使代码更难阅读。 So don't do it like that.所以不要那样做。

If you for some reason really want the extra variables, the correct syntax is:如果你出于某种原因真的想要额外的变量,正确的语法是:

int (*loc_1)[column] = matrix_1;

which makes loc_1 a pointer to an array of 'column' int.这使loc_1成为指向“列”int 数组的指针。

This:这个:

*(loc_3+i+j) = *(loc_1+i+j) + *(loc_2+i+j);

is the part where you dereferenced the pointers wrong.是您错误地取消引用指针的部分。 Matrixes are saved in C as double arrays, first is the array of pointers that represent rows, and each pointer is pointing to an array of type you defined, in your case int that represents columns.矩阵在 C 中保存为双数组,首先是表示行的指针数组,每个指针都指向您定义的类型数组,在您的情况下是表示列的 int。 So the correct way for this addition to work would be:因此,此添加工作的正确方法是:

*(*(loc_3+i)+j) = *(*(loc_1+i)+j) + *(*(loc_2+i)+j);

And variables should be defined as:变量应定义为:

int **loc_1=matrix_1;
int **loc_2=matrix_2;
int **loc_3=matrix_3;

Edit: As comments pointed out the given answer is totaly wrong with given structures.编辑:正如评论指出的那样,给定的答案对于给定的结构是完全错误的。 To give this answer any point after using dynamic allocation for matrix_n the answer can work.要在对 matrix_n 使用动态分配后给出这个答案,答案可以工作。 So if this correction is made the code gives no error.因此,如果进行此更正,则代码不会出错。 Replacement for matrix_n definition:替换 matrix_n 定义:

//int matrix_1[row][column];
//int matrix_2[row][column];
//int matrix_3[row][column];              //Resultant Matrix
int **matrix_1;
int **matrix_2;
int **matrix_3;              //Resultant Matrix

matrix_1 = malloc(row * sizeof(int*));
matrix_2 = malloc(row * sizeof(int*));
matrix_3 = malloc(row * sizeof(int*));

for (i = 0; i < row; i++)
    matrix_1[i] = (int*)malloc(column * sizeof(int));
for (i = 0; i < row; i++)
    matrix_2[i] = (int*)malloc(column * sizeof(int));
for (i = 0; i < row; i++)
    matrix_3[i] = (int*)malloc(column * sizeof(int));

Edited the answer to fit the spirit of the question where it was asked how to add matrixes using pointers.编辑了答案以符合问题的精神,其中询问如何使用指针添加矩阵。

Use functions and pointers to arrays.使用函数和指向数组的指针。

void addMatrix(size_t cols, size_t rows, int (*m1)[cols], int (*m2)[cols], int (*result)[cols])
{
    for(size_t row = 0; row < rows; row++)
    {
        for(size_t col = 0; col < cols; col++)
            result[row][col] = m1[row][col] + m2[row][col];
    }
}

void *allocMatrix(size_t rows, size_t cols)
{
    int (*matrix)[rows][cols];
    return malloc(sizeof(*matrix)); //lets compiler do the math
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM