2

Why the last printf in the main function doesn't print to the screen the value 10? I know that in ANSI C, statically allocated matrix are arranged in memory in this way: matrix: matrix[0][0], matrix[0][1],...,matrix[0][ColumnsDimension-1],matrix[1][0], etc

#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;
}
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105

5 Answers5

3

Use *(matrice[i * dimColonne] + j) instead.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Thanks! I don't understand just one thing: why a have to derefence matrice two times? It's not just a big array which contains the elements of my matrix? – MasterChief Feb 06 '12 at 20:10
  • 1
    You write `matrice[0][3]` to avoid making mistakes like this! Don't try to work out these offsets yourself. Let the compiler do the heavy lifting. It won't make mistakes. You will. – David Heffernan Feb 06 '12 at 20:12
  • @MasterChief `matrice` is an array of array of `int`. The value of `matrice` is a pointer to an array `dimColonne` of `int`. So to access the `int` element, two dereferences are required: either through `*` or `[]` operators. – ouah Feb 06 '12 at 20:14
1

Why the last printf in the main function doesn't print to the screen the value 10?

Because matrice is an array of arrays ...
and matrice[whatever] is an array (which in most circunstances "decays" to a pointer to its first element)

and *matrice[whatever] is the contents of the first element of the array matrice[whatever].

pmg
  • 106,608
  • 13
  • 126
  • 198
1

In your code you have:

matrice[i*dimColonne+j]

Since i is 0 this evaluates to

matrice[j]

Since j is 3 this means

matrice[3]

When you print *matrice[3] that is equivalent to printing matrice[3][0] because matrice[3] is an array. And an array decays to a pointer to its first element.

But you don't want to do it this way at all. You should simply write matrice[i][j] and let the compiler do the work.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

Change

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

to simply be

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

if all you're worred about is printing out the right value. After all, that's how you assigned it.

If you're doing this as an exercise to understand how array subscripting works, then there are several things you need to remember.

First, except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with ("decay to") an expression of type "pointer to T", and its value will be the address of the first element of the array. The expression matrice is an array expression of type "20-element array of 30-element array of int"; in most circumstances, it will be converted to an expression of type "pointer to 30-element array of int", or int (*)[30]. Similarly, the expression matrice[i] is an expression of type "30-element array of int", and in most cirumstances it will be converted to an expression of type "pointer to int", or int *.

Here's a handy table to remember all of this:

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

Second, the subscripting operation a[i] is defined as *(a + i); that is, you compute an address based on i number of elements (NOT BYTES) from the base address of your array and dereference the result. For example, if a is an array of int, then *(a + i) will give you the value of the i'th integer after a. If an is an array of struct foo, then *(a + i) will give you the value of the i'th struct after a. Pointer arithemtic always takes the size of the base type into account, so you don't need to worry about the number of bytes in the offset.

The same logic applies to multidimensional arrays, you just apply the rule recursively for each dimension:

    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)  

Note that you should almost never have to do these dereferences manually; a compiler knows what an array access looks like and can optimize code accordingly. Under the right circumstances, writing out the dereferences manually can result in slower code than using the subscript operator.

You can index into a 2-d array as if it were a 1-d array like so:

a[i*rows + j] = val;

but I wouldn't (the types of the expressions don't match up cleanly). Note that you multiply i by the number of rows, not columns.

John Bode
  • 119,563
  • 19
  • 122
  • 198
-1

You could also print it like this:

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

What this does is first, it converts your matrix to an array of bytes, then, it gets the starting address of the integer you need, and then it reconstructs the integer from the first four bytes read from that address.

This is a bit overkill, but a fun solution to the problem.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201