Testing validity of certain phrases in c

Viewed 79

Given as data these 3:

float pin[5];
float mat[2][4];
float* ptrf;

I have to check whether the following statements are correct or not:

ptrf = *mat;          // I think its is correct
*(mat+2) = pin[2];    // I think its false
*(mat[0]) = pin[0];   // I am not sure
ptrf = mat[1];        // I think its correct

I am trying really hard to understand how pointers work with matrixes but this is really confusing. I'd really appreciated if someone cared to explain!

2 Answers

Firstly, float ptrf* is syntactically invalid. I assume it should be float *ptrf; (ptrf is a pointer to float).

Given the declarations:

float pin[5];
float mat[2][4];
float *ptrf;

In the statement ptrf = pin;, the value (actually an lvalue) designated by pin (of type float[5]) is converted to a float* pointing to the initial element of the array. All is correct. ptrf is pointing to pin[0].

In the statement ptrf = *mat; the lvalue designated by mat (of type float[2][4]) is converted to a float(*)[4] pointing to the initial element of the outer array. (The element is itself an array of type float[4]. A type pointing to float[4] is written syntactically as float(*)[4].) The unary * operator dereferences that pointer producing an lvalue of type float[4] that is the initial row of the outer array. That lvalue of type float[4] is converted to a float* pointing to the initial element of the array. All is correct. ptrf is pointing to mat[0][0].

In the statement *(mat+2) = pin[2];, the lvalue designated by mat (of type float[2][4]) is converted to a float(*)[4] pointing to the initial element of the outer array. mat+2 points to element index 2 of the outer array. This is just past the end of the array. It is OK to point just past the final element of an array, but it is not OK to access an element there. *(mat+2) is dereferencing that non-existent element so is not OK. Also, *(mat+2) has type float[4] and arrays are not allowed on the left-hand side of an assignment because they are no longer an lvalue after conversion to a pointer to their initial element. Also, the right-hand side of the assignment has type float, which is incompatible with the left-hand side.

In the statement *(mat[0]) = pin[0];, mat[0] is the first element of the outer array and has type float[4]. That is converted to a float* pointing to its initial element. The unary * operator dereferences that pointer to an lvalue of type float. The right-hand side of the assignment pin[0] also has type float. All is correct. Note that *(mat[0]) is equivalent to mat[0][0], and it should be fairly obvious that mat[0][0] = pin[0]; is correct.

For the statement ptrf = mat[1];, remember that ptrf = *mat; was correct and note that ptrf = *mat; is equivalent to ptrf = mat[0];. The only difference for ptrf = mat[1]; is that ptrf will point to the initial element of row 1 of the matrix instead of pointing to the initial element of row 0. The matrix has 2 rows so it is OK to point to the initial element of row 1 (and it is also OK to point to the initial element of the non-existent row 2 as long as the contents of that row are not being accessed). All is correct. ptrf is pointing to mat[1][0].

First:

    ptrf = *mat;

*mat is same as mat[0] because1)

    *mat -> *(mat + 0) -> mat[0]

So, the statement can also be written as

    ptrf = mat[0];

mat[0] is the first 1D arrays of 2D array mat[2][4]. When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule).
So, mat[0] will be converted to pointer to first element of mat[0] array i.e. &mat[0][0] whose type is float * and it will be assigned to pointer ptrf.

Second:

    *(mat+2) = pin[2]; 

*(mat+2) is equivalent to mat[2]1). The type of mat[2] is float [4] i.e. array of 4 float values.
In C, array names are non modifiable lvalues. You cannot assign anything to an array but can only initialise/modify the array members. This statement the violating the language constraint hence, this is invalid. Any compiler which is compliant with the language standards will throw error message on this statement.

One thing you should also note here is that the valid value of first dimension of 2D array mat is 0 and 1. Attempt to use any other value as first dimension of mat array (for e.g. mat[2]) will lead to UB.

Third:

    *(mat[0]) = pin[0]; 

*(mat[0]) is equivalent to mat[0][0]1)

    *(mat[0]) -> *((mat[0]) + 0) -> mat[0][0]

that means, its the first member of array mat[2][4]. The type of mat[0][0] is float and the type of pin[0] is also float. This will end up assigning the value of pin[0] to mat[0][0].

Fourth:

    ptrf = mat[1];

This is same as first statement, the only difference is here it's mat[1] and in first statement it was mat[0]. This will end up assigning the address of first element of mat[1] array (i.e. &mat[1][0]) to pointer ptrf.


1). C Standards#6.5.2.1

The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..

Related