Search code examples
arrayscpointersmemory-address

Issue with pointers using arrays in C


Working with pointers and arrays in C I've found a curious case which I don't understand why it occurs.

First, I want to describe correct case: I've defined a function void modifyArray(int *list) where the array must be modified by reference to multiply items by 2 times (x2). Function implementation is:

void modifyArray(int *list, int arrLength){
    for(int i=0; i<arrLength; i++){
        *(list + i) = *(list + i) * 2; // x = x * 2
    }
}

int main(int nargs, char **args) {

    int list[] = {1,2,3,4,5};
    modifyArray(&list, 5);

    for(int i=0; i<5; i++){
        printf("%d\n", *(list + i));

    }
}

Output is:

2
4
6
8
10

Now I'm going to explain the incorrect case: I've defined a new data type List and modified the function to accept List instead of int * or int[] as first parameter:

typedef int List[5];

void modifyArray(List *list, int arrLength){
    for(int i=0; i<arrLength; i++){
        *(list + i) = *(list + i) * 2; // x = x * 2
    }
}

After modification my compiler build fails because the sentence *(list + i) = *(list + i) * 2; // x = x * 2 can't multiply bacause of the following error message:

Invalid operands to binary expression ('List' (aka 'int [5]') and 'int')

I know my compiler is trying to multiply the complete array by 2, but don't know the reason.

The solution I've found is replacing *(list + 1) by *(*list + 1). I'm confused because of in second case, when I print list and *list output is a memory address (same memory address for both) instead of a memory address for list and its content for *list.

Can you explain why this is happening and what is the difference by using int * and List defined type?


Solution

  • When list is defined with int list[] = {1,2,3,4,5};, &list is a pointer to an array of five int. It is not appropriate to pass this for a parameter of type int *, and the compiler should have issued a warning or error for that in the first code. The proper argument would be list. Although that is an array, it will be automatically converted to a pointer to its first element, and that pointer is an int *, which is the correct type for the parameter.

    When the parameter is declared as List *list, it is a pointer to an array. Then, in *(list + i), the addition is done in units of those arrays, not units of int. The result of the addition is a pointer to an array, so the result of the * in *(list + i) is an array. Then the multiplication is trying to multiply an array by two, so the compiler complains.

    Instead, declare the parameter as List list. This declares it to be an array, but it will be automatically adjusted to be a pointer to an int. Because C does not support passing arrays as parameters, it automatically adjusts a declaration of a parameter as an array to be a declaration of a pointer to an array element instead, which is supported.

    Also, do not write *(list + i). Use list[i]. It means the same thing but is easier to read.