17

I have the following program. However, I can't understand why I have to pass the address of the array. When they are both pointing to the same address. Which is the address of the first element of the array of int's.

I get a warning when I try and do this "assignment from incompatible pointer type":

ptr = var;

Complete source code:

void print_values(int (*ptr)[5])
{
    size_t i = 0;
    for(i = 0; i < 5; i++) {
        printf("%d: [ %d ]\n", i, (*ptr)[i]);
    }
}

int main(void)
{
    /* declare a pointer to an array integers */
    int (*ptr)[5] = NULL;
    /* array of integers */
    int var[] = {1, 2, 3, 4, 5};
    /* assign the address of where the array is pointing to (first element) */
    ptr = &var;
    /* Both are pointing to the exact same address */
    printf("var  [ %p ]\n",(void*)var);
    printf("&var [ %p ]\n", (void*)&var);

    print_values(ptr);
    return 0;
}

I compile the code with gcc 4.4.4 c89 -Wall -Wextra -O0

3
  • I tried to reword your title, since it was meaningless. Please, verify if I picked the gist of your problem correctly. Commented Aug 17, 2010 at 16:40
  • I think your title sounds better than mine. Thanks. Commented Aug 18, 2010 at 2:06
  • You code snippet compiles fine. Do you mean you would get an error if you added ptr = var to main? Commented Jul 21, 2015 at 14:56

4 Answers 4

25

It's purely a type issue.

In most expression contexts the name of an array (such as var) decays to a pointer to the initial element of the array, not a pointer to the array. [Note that this doesn't imply that var is a pointer - it very much is not a pointer - it just behaves like a pointer to the first element of the array in most expressions.]

This means that in an expression var normally decays to a pointer to an int, not a pointer to an array of int.

As the operand of the address-of operator (&) is one context where this decay rule doesn't apply (the other one being as operand of the sizeof operator). In this case the type of &var is derived directly from the type of var so the type is pointer to array of 5 int.

Yes, the pointers have the same address value (the address of an arrays first element is the address of the array itself), but they have different types (int* vs int(*)[5]) so aren't compatible in the assignment.

ISO/IEC 9899:1999 6.3.2.1/4:

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 of type "pointer to type" that points to the initial element of the array object and is not an lvalue. ...

Sign up to request clarification or add additional context in comments.

2 Comments

I thought that arrays only decay into pointers when called in a function. so in the expression. int arr[5] = {1,2,3,4,5}; int *ptr = arr; The arry would decay into a pointer when assigned to a pointer?
@robUK: It's not just function calls, it's most expression contexts where the decay occurs. The array decays when used to initialize a pointer; a pointer value is needed to initialize an a pointer to int, not an array of int.
6

var itself is a (*int) pointing to the first element in your array. Pointers and arrays in C extremely similar. Change int (*ptr)[5] = NULL; to int* ptr = NULL; and ptr = &var; to ptr = var;

Comments

4

C is a strongly typed language. When a function expects a parameter of type int *, you have to pass an argument of type int *. Not double *, not char *, but int *. Even if the actual numerical address in those double * or char * is "the same" as the one you want to pass, it still doesn't change anything - you still have to pass an int *. The language prohibits you from passing the value of wrong type.

This is exactly what happens in your case. The function takes a parameter of type int (*)[5]. That means that you have to pass the argument of that type. Passing an int * instead is not allowed. Whether the address is the same makes no difference.

Comments

1

From what I can tell you are assigning an array pointer (var) to a pointer that points to an array pointer ((*ptr)[5]), so that's why you get that warning.

Instead, try using

int *ptr = NULL;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.