Is the use of (arr+2)[0] right? - c

I am a student who will be a freshman in an university after this summer vacation.I want to learn about computer programing in advance but I run into some problems.
Why when I run the program in devc++,the result is -1 and 44?
When I read the book called Pointers On C,In the chapter on functions,the book says that the name of array is a pointer,and in C language arr[m]=*(arr+m),and arr[0] is composed by a pointer and a [number],so can I come to a conclusion that (arr+2),which is a pointer,and[0],can compose (arr+2)[0] equaling to *(arr+2+0)?
int main(void)
{
int arr[10];
for(int i=0;i<10;i++)
{
arr[i]=i+1;
}
int b=*(arr+1);
int c=(arr+2)[0];//Is this true?
printf("%d\n",b);
printf("%d",c);
return 0;
}

Is the use of (arr+2)[0] right?
Linguistically yes. But very questionable practice.
The beautiful invention of C is pointer arithmetic and that is exemplified by the definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
So by definition (arr+2)[0] is the same as (*((arr+2)+(0))) and simplifies to *(arr+2) and arr[2] simplifies to the same thing.
Array subscripting in C is syntactic sugar on pointer arithmetic. The term 'syntatic sugar' is sometimes overused. But in this case it really is just syntactic sugar.
The example demonstrates a critically important fact about how C manages arrays. Pointer arithmetic works in units of the type (measured in bytes they occupy) and array subscripting the same. So adding to a pointer (arr+2) and subscripting into an array (arr[2]) have a fundamental relationship.
When you understand that and realise the that array subscripts start at 0 because of that because they're offsets you get "C" as a language.
Please never write code like that. Writing code like 7[A] gets funny looks.

There is a typo in your code
for(int i=0;i<10;i++)
{
arr[0]=i+1;
}
It seems you mean
for(int i=0;i<10;i++)
{
arr[i]=i+1;
}
From the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
So the expression
(arr+2)[0]
evaluates like
*( ( arr + 2 ) + 0 )
That is the same as
*( arr + 2 )
and in turn is the same as
arr[2]
You even may write
2[arr]
Pay attention to that the expression
(arr+2)[0]
will be more clear if to introduce an intermediate pointer like
int *p = arr + 2;
and then to use the expression
p[0]

C allows you to do all sorts of clever things with arrays and pointers.
This is either a good thing (if you like writing clever code) or very frustrating (if later you have to maintain some of that clever code)
All of the following are equivalent:
(arr+2)[0]
arr[2]
2[arr]
*( ( arr + 2 ) + 0 )
*( arr + 2 )
While they are equivalent, that doesn't necessarily mean you should use them interchangeably - my general recommendation is to use array notation when accessing an array, and pointer arithmetic when indexing into any other structures. Decaying an array into a pointer is prone to errors!
In noting that you have defined your data structure as an array int arr[10]; my advice would be to access it as arr[2] - then everyone is clear what you are trying to do, both now and in teh future.
As an aside (and see profile for affiliation) MISRA C dedicates a whole chapter (8.11) to pointer type conversion, and another (8.18) to the pitfalls of arrays and pointers - a fair bit of guidance and a total of 17 Rules between them...

#include <stdio.h> // printf
int main(void)
{
int arr[10];
printf("fill and print the array\n");
for(int i=0;i<10;i++)
{
arr[i]=i+1;
printf("%d -th element of the array = arr[%d] = %d\n",i+1, i, arr[i]);
}
printf("pointer arithmetic in c \n");
int b=*(arr+1); // arr[m]=*(arr+m)
int c=(arr+2)[0];//(arr+2)[0] = *(arr+2+0)
int n = 0;
printf("%d -th element of the array = arr[%d] = %d\n",n+1, n , *(arr + n));
printf("%d -th element of the array = %d\n",2,b);
printf("%d -th element of the array = %d\n",3,c);
return 0;
}
compile
gcc t.c -Wall -Wextra
run
./a.out
result:
fill and print the array
1 -th element of the array = arr[0] = 1
2 -th element of the array = arr[1] = 2
3 -th element of the array = arr[2] = 3
4 -th element of the array = arr[3] = 4
5 -th element of the array = arr[4] = 5
6 -th element of the array = arr[5] = 6
7 -th element of the array = arr[6] = 7
8 -th element of the array = arr[7] = 8
9 -th element of the array = arr[8] = 9
10 -th element of the array = arr[9] = 10
pointer arithmetic in c
1 -th element of the array = arr[0] = 1
2 -th element of the array = 2
3 -th element of the array = 3
HTH

Related

This program sets every row's 3rd element's value to 20. Why doesn't it work?

Here's the code that I am trying to work with.
int main(void) {
int array[2][5];
for (int ** p = array; p < array + 2; p++) {
*((*p) + 2) = 20;
}
for (int row = 0; row < 2; row++) {
for (int col = 0; col < 5; col++) {
printf("%d ", array[row][col]);
}
printf("\n");
}
return EXIT_SUCCESS;
}
And this is the output given out by the compiler.
main.c:11:21: warning: initialization of 'int **' from incompatible pointer type 'int (*)[5]' [-Wincompatible-pointer-types]
11 | for (int ** p = array; p < array + 2; p++) {
| ^~~~~
main.c:11:30: warning: comparison of distinct pointer types lacks a cast
11 | for (int ** p = array; p < array + 2; p++) {
| ^
main.exe
make: *** [Makefile:7: main] Error -1073741819
I clearly don't understand type casting when it comes to multidimensional arrays. It would really help if you could explain why this doesn't work.
Omitting the first for loop and doing things manually like this do seem to give out the intended result.
*((*array) + 2) = 20;
*(*(array + 1) + 2) = 20;
I can't get the hang of "int (*)[5]".
The type of array is int [2][5], an array of two arrays of 5 int.
When an array is used in an expression other than as the operand of sizeof, the operand of unary &, or as a string literal used to initialize an array, it is automatically converted to a pointer to its first element.
Since the type of array is int [2][5], the type of its first element is int [5], an array of 5 int. So the type of a pointer to its first element is int (*)[5], a pointer to an array of 5 int.
There is no rule that a pointer to an array is converted to a pointer to a pointer. So no further automatic conversion happens. The result of using array in an expression where it is automatically converted is an int (*)[5].
Therefore, p should be declared to be int (*)[5]:
for (int (*p)[5] = array; p < array + 2; p++)
A multi-dimensional array in C can be seen as an array of arrays. Each of the two top-level elements in array[2][5] is a one-dimensional array of 5 ints. Like any old array, array "decays" in most expressions to a pointer to its first element, that is, a pointer to an int[5]. A declaration for such a pointer would be int (*firstRow)[5] = array; (initializing it with the address to the first top-level element of array). The parentheses are necessary because the indexing operator [] has higher priority than the dereferencing operator *: int *arrayOf5Pointers[5]; would index first, and the result would be a pointer, so that it declares a real array (we can index it) whose elements in turn are pointers (we can dereference the result of the indexing). With (*firstRow)[5]; we indicate that we dereference first (the variable is a pointer) and only then index the result of the dereferencing (which must be an array).
The notation for the type of (*firstRow)[5]; (what you would use in a type cast) is, as always, the notation for a declaration without the identifier, hence int (*)[5]. That looks funny and perhaps ambiguous; but Kernighan/Richie said in their C book that the C grammar guarantees that there is only one valid position for an identifier in such a type notation. I believe them.
Your assignment int ** p = array is wrong: You cannot assign a (pointer to an array of 5 ints) to (a pointer to pointer to int). That is true even though you can legitimately access the first element of the two-dimensional array with e.g. int i = **array;: array decays to a pointer to its first element, that is, to a pointer to an array of 5 ints; the first dereferencing results in the actual array of 5 ints; which in turn decays to a pointer to its first int element; which is dereferenced with the second *.
The general takeaway here is: Pointers to arrays are rare and typically unnecessary. Simply index your 2-dimensional array in the normal fashion:
for(int row = 0; row < 2; row++) { array[row][2] = 20; }
or, better,
for(int row = 0; row < sizeof array/sizeof *array; row++) { array[row][2] = 20; }
The latter determines the number of top-level elements in the array by dividing its overall size in bytes by the size of its first element. The loop stays correct even if you change the size of array.

Using pointers to get value from multidimensional array - C

I am trying to get value from "second row" in multidimensional array. But I have some problems with that.
I thought that numbers are stored sequentialy in memory so tab[2][2] is stored same as tab[4]. But it seems that I was wrong.
This is what I tried:
int b[2][2] = {{111,222},{333,444}};
int i = 0;
for(;i < 100; i++)
printf("%d \n", **(b+i));
The problem is that I get only 111 and 333 as the result. There is no 222 or 444 in other 98 results. Why?
The problem is that **(b+i) doesn't do what you think it does. It evaluates to:
b[i][0]
As Matt McNabb noted,
**(b+i)
is equivalent to:
*(*(b+i)+0)
and since *(b+i) is equivalent to b[i], the expression as a whole can be seen as:
*(b[i]+0)
and hence:
b[i][0]
Since your array has only 2 rows, only the values of i for 0 and 1 are in bounds of the array (that's the 111 and 333). The rest was wildly out of bounds.
What you could do is:
#include <stdio.h>
int main(void)
{
int b[2][2] = { { 111, 222 }, { 333, 444 } };
int *base = &b[0][0];
for (int i = 0; i < 4; i++)
printf("%d: %d\n", i, base[i]);
return 0;
}
Output:
0: 111
1: 222
2: 333
3: 444
You can think of a two-dimensional array as a special form of a one-dimensional array. Your array holds 2 elements (!). (Each element happens to be an array of two elements, but let's ignore that for a sec.) Let's make the dimensions different so that we can distinguish them:
int arr2d[2][3] holds 2 elements (each being an array of 3 elements). The "primary index" is written first, that is if you have a one-dimensional array of 3 like int arr1d[3]and want to have an array of those with three elements like arr2d, you have to write arr2d[2][3]. You could arrange that with a typedef which makes it clear that all arrays in C are essentially 1-dimensional:
typedef int arr3IntT[3];
arr3IntT arr2d[2] = { {0,1,2}, {3,4,5} };
Now what does arr2d+i mean? arr2d, like any array, decays to a pointer to its first element (which is an array of 3 ints). arr2d+1 adds the offset of 1 of those elements to the address, so that like always the expression yields the address of the second element (which is the second array of 3 ints). Dereferencing it once like *(arr2d+1) yields that element, i.e. the one-dimensional sub-array of 3 ints. It decays to a pointer to its first element, i.e. a pointer to the first int in that second sub-array. Dereferencing that in the expression **(arr2d+1) yields that int, like always. To summarize: In your original code you iterate from sub-array to sub-array, always referencing the first of their elements, incidentally going out of bounds for i>1.
But principally you are right, elements of n-dimensional arrays in C are lying contiguously in memory, so you can access them one by one if you like to. You just have to index a pointer to int, not one to int[3]. Here is how: The expression arr2d decays to a pointer to its first element which is an array of 3 ints. Dereferencing that gives that first element, a one-dimensional array of 3 ints. Like all arrays, it decays to a pointer to its first element, an int, which is the very first element in the data:
#include<stdio.h>
int main()
{
int arr2d[2][3] = { {0,1,2}, {3,4,5} };
int *p_el1 = *arr2d;
int i, j;
// Sanity check by indexing 2-dimensionally
for(i=0; i<2; i++) for(j=0; j<3; j++) printf("%d\n", arr2d[i][j]);
// iterate the elements 1 by 1
for(i=0; i<3*2; i++) printf("%d\n", p_el1[i]);
}
A multidimensional array is not a fundamentally new type. It's an array type where the elements are themselves arrays. To quote the C99 standard §6.2.5 ¶20 (Types)
An array type describes a contiguously allocated nonempty set of
objects with a particular member object type, called the element type.
Array types are characterized by their element type and by the number
of elements in the array.
int b[2][2] = {{111, 222}, {333, 444}};
The above statement defines b to be an array of 2 elements where each element is the type int[2] - an array of 2 integers. It also initializes the array with the array initializer list. An array is implicitly converted to a pointer to its first element in some cases.
In the printf call, b decays to a pointer to its first element. Therefore, it's equivalent to &b[0] and has type int (*)[2] - a pointer to an array of 2 integers. Please note that it's undefined behaviour to access elements out of the bound of an array. Therefore, the for loop condition i < 100 is wrong. It should be i < 2. Now, let's try to demystify the expression **(b+i).
b -------------> pointer to a[0]
b + i ---------> pointer to a[i]
*(b + i) -----> a[i]
*(*(b + i)) ---> *(a[i]) ----> *(&(a[i])[0]) ----> a[i][0]
As noted, the elements of the array are themselves arrays. Therefore, a[i] is an array. Again, the array decays to a pointer to its first element, i.e., to &(a[i])[0]. Applying indirection operator * on this pointer gets us the value at that address which is a[i][0].
You can access the elements of the array through a pointer but the pointer type must be a pointer to element type of the array.
#include <stdio.h>
int main(void) {
int b[2][2] = {{111, 222}, {333, 444}};
int (*p)[2] = b;
// (sizeof b / sizeof b[0]) evaluates to
// the size of the array b
for(int i = 0; i < (sizeof b / sizeof b[0]); i++)
// (sizeof *p / sizeof (*p)[0]) evaluates to
// the size of element of the array which is
// itself an array.
for(int j = 0; j < (sizeof *p / sizeof (*p)[0]); j++)
printf("%d\n", *(*(p + i) + j));
return 0;
}
Here, the expression *(*(p + i) + j) can be decoded as
p ---------------> pointer to the first element of b, i.e., &b[0]
(p + i) ----------> pointer to b[i], i.e., &b[i]
*(p + i) ---------> the array element b[i] ---> decays to &(b[i])[0]
*(p + i) + j -----> &(b[i])[j]
*(*(p + i) + j) --> the element b[i][j]
Therefore, the expression *(*(p + i) + j) is equivalent to b[i][j]. In fact, the C99 standard §6.5.2.1 ¶2 says -
The definition of the subscript operator [] is that E1[E2] is
identical to (*((E1)+(E2)))
This means we have the following are equivalent with context to the above program -
*(*(p + i) + j)
// equivalent to
p[i][j]
// equivalent to
b[i][j]
// equivalent to
*(*(b + i) + j)

Arrays and pointers in C

I have this piece of program and there are some parts that I don't understand...
‪#‎include‬ <stdio.h>
void increment( int *ptr) {++*ptr; }
int main(){
int a[] = { 5, 10 }, i = 0; // We have: vector a=[5,10] | i=0
increment(a); //This is the same as increment(&a) isn't it?
//So we have: a=[6,10] | i=0
increment(&i); // We increment i so: a=[6,10] | i=1
increment(&a[i]); //We increment the element at the position a[1]: a=[6,11] | i=1
increment(a+i); //OMG! What does it mean? a is an array isn't it? Then how can we
//make "a+1"? and how is this an address?
printf("\nResult: i= %d\n", i);
printf( "a[0] = %d\n" "a[1] = %d\n", a[0], a[1]);
return 0;
}
The printfs return:
i=1
a[0]=6
a[1]=12
How can this be explained?
When you pass an array to a function, the array decays to a pointer to the first element. So in the function, doing e.g. *ptr is dereferencing the first element in the array.
Also, because arrays decays to pointers, doing e.g. a[i] is equal to *(a + i).
Unrelated side-note: Because of the commutative of addition, the expression *(a + i) can be written as *(i + a) which leads to i[a] actually being a valid expression.
Arrays and pointer arithmetic are the same in C. If you've not come across pointer arithmetic here's a tutorial on it:
C Pointer Arithemtic
In essence:
a[3]
is the same as
*(a + 3)
Where a is a pointer.
When we give the name of array in the function call, the address of the arrya's first element is passed
ie; increment(a); is same as increment(&a[0]);
So while giving
incrementa(a+i);
since i and array a[] are both integers effectively that becomes
incrementa ( base address of array a (ie; &a[0]) + value of i )
i just acts as the offset to that array element
That it becomes the address of the second element which is &a[1]
so the 11 is modified to 12 while incrementing the value by the function

Confusion with Two Dimensional Array

Please consider the following 2-D Array:
int array[2][2] = {
{1,2},
{3,4}
};
As per my understanding:
- 'array' represents the base address of the 2-D array (which is the same as address of the first element of the array, i.e array[0][0]).
The actual arrangement of a 2-D Array in memory is like a large 1-D Array only.
Now, I know that base address = array. Hence, I should be able to reach the Memory Block containing the element: array[0][0].
If I forget about the 2-D array thing & try to treat this array as a simple 1-D array:
array[0] = *(array+0) gives the base address of the first array & NOT the element array[0][0]. Why?
A 2-D array does not store any memory address (like an Array of Pointers).
If I know the base address, I must be able to access this memory as a linear 1- Dimensional Array.
Please help me clarify this doubt.
Thanks.
array[0] is a one-dimensional array. Its address is the same as the address of array and the same as the address of array[0][0]:
assert((void*)&array == (void*)&(array[0]));
assert((void*)&array == (void*)&(array[0][0]));
Since array[0] is an array, you can't assign it to a variable, nor pass it to a function (if you try that, you'll be passing a pointer to the first element instead). You can observe that it's an array by looking at (array[0])[0] and (array[0])[1] (the parentheses are redundant).
printf("%d %d\n", (array[0])[0], (array[0])[1]);
You can observe that its size is the size of 2 int objects.
printf("%z %z %z\n", sizeof(array), sizeof(array[0]), sizeof(array[0][0]));
Here's a diagram that represents the memory layout:
+-------------+-------------+-------------+-------------+
| 1 | 2 | 3 | 4 |
+-------------+-------------+-------------+-------------+
`array[0][0]' `array[0][1]' `array[1][0]' `array[1][1]'
`---------array[0]---------' `---------array[1]---------'
`-------------------------array-------------------------'
"Thou shalt not fear poynter arythmethyc"...
int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)&array[0][0];
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", ptr[i]);
}
Why does this work? The C standard specifies that multidimensional arrays are contigous in memory. That means, how your 2D array is arranged is, with regards to the order of its elements, is something like
array[0][0]
array[0][1]
array[1][0]
array[1][1]
Of course, if you take the address of the array as a pointer-to-int (int *, let's name it ptr), then the addresses of the items are as follows:
ptr + 0 = &array[0][0]
ptr + 1 = &array[0][1]
ptr + 2 = &array[1][0]
ptr + 3 = &array[1][1]
And that's why it finally works.
The actual arrangement of a 2-D Array in memory is like a large 1-D Array only.
yes, the storage area is continuous just like 1D arrary. however the index method is a little different.
2-D[0][0] = 1-D[0]
2-D[0][1] = 1-D[1]
...
2-D[i][j] = 1-D[ i * rowsize + j]
...
If I forget about the 2-D array thing & try to treat this array as a simple 1-D array: array[0] = *(array+0) gives the base address of the first array & NOT the element array[0][0]. Why?
the *(array+0) means a pointer to a array. the first element index in such format should be *((*array+0)+0).
so finally it should be *(*array)
A 2-D array does not store any memory address (like an Array of Pointers).
of course, you can . for example ,
int * array[3][3] ={ null, };
If I know the base address, I must be able to access this memory as a linear 1- Dimensional Array.
use this formal 2-D[i][j] = 1-D[ i * rowsize + j]...
Arrays are not pointers.
In most circumstances1, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
The type of the expression array is "2-element array of 2-element array of int". Per the rule above, this will decay to "pointer to 2-element array of int (int (*)[2]) in most circumstances. This means that the type of the expression *array (and by extension, *(array + 0) and array[0]) is "2-element array of int", which in turn will decay to type int *.
Thus, *(array + i) gives you the i'th 2-element array of int following array (i.e., the first 2-element array of int is at array[0] (*(array + 0)), and the second 2-element array of int is at array[1] (*(array + 1)).
If you want to treat array as a 1-dimensional array of int, you'll have to do some casting gymnastics along the lines of
int *p = (int *) array;
int x = p[0];
or
int x = *((int *) array + 0);
1. The exceptions are when the array expression is an operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration.
I like H2CO3's answer. But you can also treat the pointer to the array as an incrementable variable like so:
int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 4; i++)
{
printf("%d\n", *ptr);
ptr++;
}
the ++ operator works on pointers just fine. It will increment the pointer by one address of it's type, or size of int in this case.
Care must always be used with arrays in c, the following will compile just fine:
int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 100; i++) //Note the 100
{
printf("%d\n", *ptr);
ptr++;
}
This will overflow the array. If you are writing to this you can corrupt other values in the program, including the i in the for loop and the address in the pointer itself.

Matrix Access Ansi C

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;
}
Use *(matrice[i * dimColonne] + j) instead.
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].
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.
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.
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.

Resources