Reputation: 81
I am new to C and spend some hours with arrays and pointers. Now, I got a specific question I can't really answer by myself. What are the two variables mat_ptr and ptr which I create in this example and why are they different? To me it looks like each is an array of pointers storing the pointers to the beginning of the 3 rows of the matrix.
int matrix[3][3] = {{0,1,2},
{0,1,2},
{0,1,2}};
int (*mtr_ptr)[3] = matrix;
int *ptr[3];
for (int i=0; i< 3; i++)
{
ptr[i]=matrix[i];
}
I the end, I think ptr ist of type int **
but what exactly is ptr_ptr?
A pointer to an array of size 3 which is an array of arrays?
Upvotes: 1
Views: 101
Reputation: 123598
Unless it is the operand of the sizeof
or unary &
operators, or is a string literal used to initialize a character array in a declaration, 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.
In the line
int (*mtr_ptr)[3] = matrix;
the expression matrix
has type "5-element array of 5-element array of int
". Since matrix
is not the operand of the sizeof
or unary &
operators, it "decays" to type "pointer to 5-element array of int
", or int (*)[5]
, and its value is the address of the first element of matrix
(same as &matrix[0]
).
int (*)[5]
and int (*)[3]
are different, incompatible types, so the compiler should yak at you on that initializer. You should declare mtr_ptr
as
int (*mtr_ptr)[5] = matrix;
Remember that mtr_ptr
is a pointer, not an array - it stores a single value.
That single value has type int (*)[5]
.
By contrast, the expression matrix[i]
has type "5-element array of int
"; by the same rule above, that expression "decays" to type "pointer to int
", or int *
. Since each element of your ptr
array is storing an int *
, you declare it as
int *ptr[3];
In this case ptr
is an array, and each element simply stores an int *
. That pointer may be the address of the first element matrix[i]
, or it may be a pointer to a single int
object that isn't part of a larger array, or it may be something else:
ptr[0] = matrix[0];
ptr[1] = &i;
...
The size of ptr
does not depend on the size of matrix
beyond whether or not you want to store the address of all rows or matrix
or just a subset.
Upvotes: 0
Reputation: 311146
These declarations
int matrix[5][5] = {{0,1,2,3},
{0,1,2,3},
{0,1,2,3}}
int (*mtr_ptr)[3] = matrix;
do not make a sense. It seems you mean at least the following declarations
int matrix[3][4] = {{0,1,2,3},
{0,1,2,3},
{0,1,2,3}};
int (*mtr_ptr)[4] = matrix;
According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
So the array matrix used in expressions with rare exceptions is converted to pointer to its initial element of the type int ( * )[4]
.
Thus in this declaration
int (*mtr_ptr)[4] = matrix;
the pointer mtr_ptr
is initialized by the address of the first "row" of the array matrix
.
On the other hand, the expression matrix[i]
is the i-th element of the array matrix
that has the type int[4]
. Such an array used in expression is in turn converted to pointer to its first element of the type int *
.
In this line
int *ptr[3];
there is declared an array of three elements of the type int *
.
And in this loop
for (int i=0; i< 3; i++)
{
ptr[i]=;
}
each element of the array of pointers is assigned by the address of the first element of the corresponding "row" of the array matrix
that ("row") used in the expression matrix[i]
is implicitly converted to pointer.
Upvotes: 0
Reputation: 17513
First things first. There is a semi-colon missing from the definition of matrix
, corrected below:
int matrix[5][5] = {{0,1,2,3},
{0,1,2,3},
{0,1,2,3}};
Regarding the definition of mtr_ptr
below:
int (*mtr_ptr)[3] = matrix;
mtr_ptr
is declared as a pointer to an array length 3 of int
s. However, it is being initialized with an incompatible pointer. matrix
is an array length 5 of array length 5 of int
. In the assignment expression above, matrix
is converted to a pointer to the first element. The elements of matrix
have type array length 5 of int
, so matrix
is converted to a pointer to array length 5 of int
with value equivalent to &matrix[0]
. Therefore, mtr_ptr
should be defined as:
int (*mtr_ptr)[5] = matrix;
or equivalently:
int (*mtr_ptr)[5] = &matrix[0];
Regarding the code below:
int *ptr[3];
for (int i=0; i< 3; i++)
{
ptr[i]=matrix[i];
}
ptr
is defined as an array length 3 of pointers to int
. matrix[i]
is an array length 5 of int
. In the assignment expression, it is converted to a pointer to its first element. The element type is int
, so matrix[i]
is converted to a pointer to int
equivalent to &matrix[i][0]
. Therefore, the assignement ptr[i]=matrix[i];
is equivalent to ptr[i]=&matrix[i][0];
.
Upvotes: 0
Reputation: 224546
This code:
int matrix[5][5] = {{0,1,2,3},
{0,1,2,3},
{0,1,2,3}}
is missing a semicolon at the end. When that is fixed, it defines matrix
to be a 5×5 array (formally an array of 5 arrays of 5 int
) in which rows 0 to 2 are initialized with four values (0, 1, 2, and 3), leaving element 4 implicitly initialized to zero. Rows 3 to 4 are implicitly initialized to zero.
This code:
int (*mtr_ptr)[3] = matrix;
defines mtr_ptr
to be a pointer to an array of 3 int
and attempts to initialize it with matrix
. Since matrix
is an array, it will be automatically converted to a pointer to its first element, matrix[0]
. Thus, we have a pointer to an array of 5 int
. This is not a proper type to initialize a pointer to an array of 3 int
, so the compiler will complain.
If matrix
were defined as int matrix[5][3]
or int matrix[3][3]
, and the then-excess initializers were removed, then the types in int (*mtr_ptr)[3] = matrix;
would match, and the compiler would not complain.
This code:
int *ptr[3];
for (int i=0; i< 3; i++)
{
ptr[i]=matrix[i];
}
defines an array of 3 pointers to int
and assigns them values from matrix[i]
. Since each matrix[i]
is an array, it will be converted to a pointer to its first element, matrix[i][0]
. So each ptr[i]
will be assigned to point to matrix[i][0]
.
Upvotes: 2