C subscripted value is neither array nor pointer nor vector when assigning an array element value

Sorry for asking the already answered question, I am a newbie to C and don’t understand the solutions. Here is my function

int rotateArr(int *arr) {
    int D[4][4];
    int i = 0, n =0;
    for(i; i < M; i ++ ){
        for(n; n < N; n++){
            D[i][n] = arr[n][M - i + 1];
        }
    }
    return D;
}

It throws an error

main.c|23|error: subscripted value is neither array nor pointer nor vector|

on line

D[i][n] = arr[n][M – i + 1];

What’s wrong? I am just setting the value of an array element to another array element.

The arr passed is declared as

int S[4][4] = { { 1, 4, 10, 3 }, { 0, 6, 3, 8 }, { 7, 10 ,8, 5 },  { 9, 5, 11, 2}  };

6 Answers

C lets you use the subscript operator [] on arrays and on pointers. When you use this operator on a pointer, the resultant type is the type to which the pointer points to. For example, if you apply [] to int*, the result would be an int.

That is precisely what’s going on: you are passing int*, which corresponds to a vector of integers. Using subscript on it once makes it int, so you cannot apply the second subscript to it.

It appears from your code that arr should be a 2-D array. If it is implemented as a “jagged” array (i.e. an array of pointers) then the parameter type should be int **.

Moreover, it appears that you are trying to return a local array. In order to do that legally, you need to allocate the array dynamically, and return a pointer. However, a better approach would be declaring a special struct for your 4×4 matrix, and using it to wrap your fixed-size array, like this:

// This type wraps your 4x4 matrix
typedef struct {
    int arr[4][4];
} FourByFour;
// Now rotate(m) can use FourByFour as a type
FourByFour rotate(FourByFour m) {
    FourByFour D;
    for(int i = 0; i < 4; i ++ ){
        for(int n = 0; n < 4; n++){
            D.arr[i][n] = m.arr[n][3 - i];
        }
    }
    return D;
}
// Here is a demo of your rotate(m) in action:
int main(void) {
    FourByFour S = {.arr = {
        { 1, 4, 10, 3 },
        { 0, 6, 3, 8 },
        { 7, 10 ,8, 5 },
        { 9, 5, 11, 2}
    } };
    FourByFour r = rotate(S);
    for(int i=0; i < 4; i ++ ){
        for(int n=0; n < 4; n++){
            printf("%d ", r.arr[i][n]);
        }
        printf("n");
    }
    return 0;
}

This prints the following:

3 8 5 2 
10 3 8 11 
4 6 10 5 
1 0 7 9 

You are not passing your 2D array correctly. This should work for you

int rotateArr(int *arr[])

or

int rotateArr(int **arr) 

or

int rotateArr(int arr[][N]) 

Rather than returning the array pass the target array as argument. See John Bode’s answer.

Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type “N-element array of T” is converted (“decays”) to an expression of type “pointer to T“, and the value of the expression is the address of the first element of the array.

If the declaration of the array being passed is

int S[4][4] = {...};

then when you write

rotateArr( S );

the expression S has type “4-element array of 4-element array of int“; since S is not the operand of the sizeof or unary & operators, it will be converted to an expression of type “pointer to 4-element array of int“, or int (*)[4], and this pointer value is what actually gets passed to rotateArr. So your function prototype needs to be one of the following:

T rotateArr( int (*arr)[4] )

or

T rotateArr( int arr[][4] )

or even

T rotateArr( int arr[4][4] )

In the context of a function parameter list, declarations of the form T a[N] and T a[] are interpreted as T *a; all three declare a as a pointer to T.

You’re probably wondering why I changed the return type from int to T. As written, you’re trying to return a value of type “4-element array of 4-element array of int“; unfortunately, you can’t do that. C functions cannot return array types, nor can you assign array types. IOW, you can’t write something like:

int a[N], b[N];
...
b = a; // not allowed
a = f(); // not allowed either

Functions can return pointers to arrays, but that’s not what you want here. D will cease to exist once the function returns, so any pointer you return will be invalid.

If you want to assign the results of the rotated array to a different array, then you’ll have to pass the target array as a parameter to the function:

void rotateArr( int (*dst)[4], int (*src)[4] )
{
  ...
  dst[i][n] = src[n][M - i + 1];
  ...
}

And call it as

int S[4][4] = {...};
int D[4][4];

rotateArr( D, S );

The problem is that arr is not (declared as) a 2D array, and you are treating it as if it were 2D.

You have “int* arr” so “arr[n]” is an int, right? Then your “[M – 1 + 1]” bit is trying to use that int as an array/pointer/vector.

the second subscript operator is invalid here. You passed a int * pointer into function, which is a 1-d array. So only one subscript operator can be used on it.

Solution : you can pass int ** pointer into funciton

Leave a Reply

Your email address will not be published. Required fields are marked *