0
void dgem(int n, double *A, double *B, double *C)
{

    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; j++){

            double cij = C[i+j*n]; /* cij = C[i][j] */

            for(int k = 0; k < n; k++){
                cij += A[i+k*n] * B[k+j*n]; /*cij = A[i][k]*b[k][j]*/
                C[i+j*n] = cij; /* C[i][j] = cij */
            }
        }
    }

}

This code is from Computer_Organization_and_Design_5th

Is it right? double cij = C[i+j*n];

As far as I know, it should be C[i*n + j]

int main(void){

    double A[4][4] = {1,2,3,4,
                      5,6,7,8,
                      9,10,11,12,
                      13,14,15,16};
    double * a = &A[0][0];

    int n = 4;
    printf("%f %f %f %f", *(*(A+1)+3), A[1][3], a[1*n + 3], a[1 + 3*n]); /* 
when i == 1 and j == 3 */

    return 0;

}

OUTPUT:

8.000000 8.000000 8.000000 14.000000

When I try with gcc, it doesn't make sense...

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Simon
  • 3
  • 3
  • 1
    Yes the above is correct – Cyclonecode May 07 '18 at 12:49
  • Thanks a lot. Can you explain the reason that [i][j] becomes [i + j*n]? – Simon May 07 '18 at 12:55
  • "Mangled 2D arrays" is antique stuff from early 90s. In modern C you always access arrays as `[i][j]`. See [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Lundin May 07 '18 at 13:04
  • I appreciate all the answers thanks! – Simon May 08 '18 at 00:39
  • @Simon - do not post pictures of text -- post the text (properly indented by 4-spaces). Your text will take ~120-bytes to store, your images will take 100 times that -- and -- we are not going to retype text from your pictures to test your code. Help us help you. – David C. Rankin May 08 '18 at 03:54
  • @DavidC.Rankin I removed the picture.. really sorry. I should have been kinder about the question. From now on, i will try to be polite. Thanks for the advise. – Simon May 08 '18 at 04:56
  • No big deal, you are new here -- you get a couple of screw-ups without being dinged. The way you can help us help you is to always post [**A Minimal, Complete, and Verifiable Example (MCVE)**](http://stackoverflow.com/help/mcve) along with any data necessary to your question. That way we can compile your code, find the problems, and confirm proper operation before helping you with an answer. Welcome to Stack Overflow... – David C. Rankin May 08 '18 at 04:59

1 Answers1

0

The below statement

double cij = C[i+j*n]; 

is correct. To understand this Lets assume double ptr[3] = {1.5,2.5,3.5] where ptr is array of three double variable. Now how will you access ptr[0] or ptr[1] etc.

 ----------------------------------------
|    1.5   |   2.5   |   3.5   |   4.5   |
-----------------------------------------
0x100     0x108    0x116     0x124     0x132 <-- lets say starting address 
LSB                                                 of ptr is 0x100
|
ptr

for row = 1

ptr[row] == *(ptr + row * sizeof(ptr[row]))
2.5      == *(0x100 + 1*8)
2.5      == *(0x108)
2.5      == 2.5

From above you can't have *(ptr*8 + row) it should be *(ptr + row*8).

Similarly if ptr is 2D array like double ptr[2][3] then

ptr[row][col] == *( *(ptr + row) + col*8)

Similarly in your case valid one is C[i + j*n] not C[i*n +j]

Edit :- you have an 2D array like below

double A[4][4] = { {1,2,3,4} , {5,6,7,8} , {9,10,11,12} , {13,14,15,16} };

And

double *a = &A[0][0];

Now it looks like

    A[0]          |   A[1]        |   A[2]           |   A[3]             |
  -------------------------------------------------------------------------
  | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |  16 |
  -------------------------------------------------------------------------
0x100 0x108...................0x156.......................0x156 (assume that 0x100 is starting address of A)
  A
  a
 LSB -->  

Now when you do a[1*n + 3]) How internally its expanded

a[1*n + 3]) == *(a + (1*n + 3)  /*note that a is double pointer, it increments by 8 bytes
a[1*n + 3]) == *(0x100 + (1*4 + 3) *8)
a[1*n + 3]) == *(0x100 + 56)
            == *(0x156)
            ==  8 /* it prints 8.000000 */

And when you do a[1+3*n]) How internally its expanded

a[1+3*n]) == *(a + (1+3*n)*8)
a[1+3*n]) == *(0x100 + (1+3*4)*8)
a[1+3*n]) == *(0x100 + 96)
          == *(0x196)
          == 14 /* it prints 14.000000 */

When you do *(*(A+1) +3)) it internally expanded as

*(*(A+1) +3)) == *( *(0x100 +1*32) + 3*8) /* A+1 means increment by size of A[0] i.e 32 */ 
*(*(A+1) +3)) == *( *(0x132) + 24)
*(*(A+1) +3)) == *( 0x132 + 24 ) == *(156)
*(*(A+1) +3)) == 8 /*it prints 8.000000 */

And When you do A[1][3] which is same as above case.

Achal
  • 11,821
  • 2
  • 15
  • 37
  • Could you please see the APPENDED PICTURE? Why is the value different between A[i][j] and A[i + j*n]? – Simon May 08 '18 at 03:53
  • Hi @Simon I modified my answer. if any other query plz ask. – Achal May 08 '18 at 04:28
  • Thanks. You are such an outstanding and nice person. Then in my code, if i want to access A[i][j], i should do a[i\*n + j]. But you said that when accessing C[i][j], C[i + j\*n] is right. I confused this part. – Simon May 08 '18 at 05:02
  • Note that `C` you declared as single double pointer, And `A` you declared as 2D array, so both are different. And don't confuse with `n` because you fixed it as `4`. – Achal May 08 '18 at 05:11
  • Thank you. I will brood over your excellent answer with the problem. – Simon May 08 '18 at 05:14