1

This is the program I'm working on. The task is to multiply 2 matrices. The number of columns in Matrix A are the same as the number of rows in Matrix B. I give the user the option to insert what the two matrices contain . this my code:

#include <stdio.h>
void multiplyMat(int n,int p,int c,int m,int d,int q,int k,int **multiply, 
int **first,int **second);
int main()
{
  int m, n, p, q, c, d, k;
  int first[10][10], second[10][10], multiply[10][10];

  printf("Enter number of rows and columns of first matrix\n");
  scanf("%d%d", &m, &n);
  printf("Enter elements of first matrix\n");

  for (c = 0; c < m; c++)
    for (d = 0; d < n; d++)
      scanf("%d", &first[c][d]);

  printf("Enter number of rows and columns of second matrix\n");
  scanf("%d%d", &p, &q);

  printf("Enter elements of second matrix\n");

  for (c = 0; c < p; c++)
     for (d = 0; d < q; d++)
        scanf("%d", &second[c][d]);

multiplyMat(n,p,c,m,d,q,k,multiply,first,second);
printf("Product of the matrices:\n");

for (c = 0; c < m; c++) {
  for (d = 0; d < q; d++)
    printf("%d\t", multiply[c][d]);
printf("\n");
}
return 0;
}

void multiplyMat(int n,int p,int c,int m,int d,int q,int k,int **multiply, 
int **first,int **second){
    int sum=0;
    if (n == p){
        for (c = 0; c < m; c++) {
           for (d = 0; d < q; d++) {
                for (k = 0; k < p; k++) {
                    sum = sum + first[c][k]*second[k][d];
                }

            multiply[c][d] = sum;
            sum = 0;
            }
        }
    }
    else
        printf("The matrices can't be multiplied with each other.\n");

}

I get the "segmentation fault". it happend when the code get in "sum = sum + first[c][k]*second[k][d]" what i do that cause it? maybe its happend because i use wrong defnion of pointers.

  • 3
    `int **multiply` is something else than your `first[10][10]`. What does your compiler tell you when you turn warnings on? – Paul Ogilvie Dec 11 '18 at 17:16
  • @PaulOgilvie: He's probably going to need a bit more explanation than that. – Robert Harvey Dec 11 '18 at 17:18
  • Searching for `[c] segmentation fault passing 2D array` will yield a *plethora* of duplicates to this question. Did you do that? – WhozCraig Dec 11 '18 at 17:21
  • The type of pointer first/second/multiply decay to is not `int**`, but `int(*)[10]`, i. e. a pointer to arrays of length 10, so something totally different... – Aconcagua Dec 11 '18 at 17:26
  • 1
    To understand the difference between actual arrays and pointers to pointers such as `int **first`, this question and the answers are highly relevant: [**Correctly allocating multi-dimensional arrays**](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Andrew Henle Dec 11 '18 at 17:38
  • @shaykeshok If you are curious what actually happens, if you convert (implicitly or explicitly) `int(*)[10]` to `int**`, assuming 32-bit int and 64-bit pointers, then the first two ints of your array are interpreted as a pointer. Let's say you have an array `int a[][10] = { { 0xa, 0xd, /*...*/ }, /* ... */ }` used as `int** p`, then `p[0][0]` will try to look up an int at address `0x0000000d0000000a` – Aconcagua Dec 11 '18 at 18:01
  • Side note: you can avoid quite a lot of trouble if you pack the 2d array into a struct and pass pointer to struct instead. – Aconcagua Dec 11 '18 at 18:23

1 Answers1

3

int **multiply is "a pointer to a pointer to an int", also interpreted as "a pointer to an array of pointers to ints".

So int **multiply and int *multiply[] are the same and you can use i= multiply[1][3]; The compiler will dereference multiply, add the size of 1 pointer, then dereference that element and add the size of 3 ints, then gets that int and assign it to i.

But you pass a 2 dimensional array. A 2 dimensional array is not an array of columns containing pointers to the rows. It just is a block of memory in which you have columns times a row laid out neatly one after the other.

Now you make a function to do the multiplication. But that function does not know how many columns a row has. So the compiler cannot evaluate multiply[1][2] as the third element of the second row of multiply[10][10].

To achieve what you want there are three possibilities:

  1. declare the matrix with a size in your function of the row size, e.g. multiply[][10]. This allows the compiler to do the address calculations inside your functions (you must still tell it how many rows there are)

  2. with modern compilers, you can dynamically specifiy the array sizes:

    f(int rows, int cols, int a[rows][cols])
    
  3. do the address calculations yourself. (I will not go into this option; I hope you have a modern compiler).

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • I dont understand. I pass "int **multiply" so why it doesnt good? – shayke shok Dec 11 '18 at 17:28
  • i use option number 2. When I put numbers in "f(int rows, int cols, int a[rows][cols])" like this: f(int rows, int cols, int a[10][10]) its work great but when i use varibels i get strange numbers in the result. – shayke shok Dec 11 '18 at 17:49
  • Just for completeness: For function parameters, `int a[rows][cols]` is equivalent to `int a[][cols]` which is equivalent to `int (*a)[cols]`, i. e. the *outermost* dimension always just is a pointer! `int a[somethingTotalltDifferent][cols]` would still be fine, as long as the `rows` parameter is set correctly. However, this does not apply for the other dimensions (i. e. `int(*)[10]` and `int(*)[12]` are *different* types). – Aconcagua Dec 11 '18 at 17:51
  • 1
    @shaykeshok, the variables must be the _size_ of the dimensions, not how many elements are in use. for example, your `m, n` are asked the user and are the number of elements in use, but they must be `10, 10` because those are the sizes of the dimensions. – Paul Ogilvie Dec 11 '18 at 18:01