Home > Enterprise >  What's the difference between int array[] and int* array and where is address of array stored (
What's the difference between int array[] and int* array and where is address of array stored (

Time:10-04

Suppose we have a program like this

int main() {
    int array[3] = { 1, 2, 3 };
    int* ptr = array; // <--- Didn't have to use a "&"
    printf("%d\n", *array);
    printf("%d\n", *ptr);
    
    return 0;
}

We would expect to get:

1
1

My questions are

  1. I read here that the "array" is not "lvalue". What does this mean?
  2. Is the "array" just a name for a block of memory? If it is, where is the address of that block stored? int* ptr = array implies that the address of the "array" block has to be stored in the "array", right?
  3. How is it different from something like this? Isn't the "point" also a name for a block of memory?
struct Point { int x; int y; };
int main() {
    struct Point point = { 1, 2 };
    struct Point* ptr = &point; // <--- Have to use a "&"
    printf("%d\n", point.x);
    printf("%d\n", ptr->x);

    return 0;
}

CodePudding user response:

  1. While the whole concept of "lvalue" is complicated, in this case it mainly means that you can't assign to it. You can't do array = something;. But you can do ptr = something;, because ptr is an lvalue.
  2. The details of data storage are implementation-dependent, but usually an automatic array will be stored on in the stack frame, just like any other automatic variables.
  3. The difference is that in many contexts, an array "decays" into a pointer to its first element. So when you write
int *ptr = array;

it's equivalent to

int *ptr = &array[0];

CodePudding user response:

  • I read here that the "array" is not "lvalue". What does this mean?

Presumably the author meant that C does not define behavior for whole-array assignment. That is, this does not conform to the language specification:

    int array1[3] = { 1, 2, 3 };
    int array2[3] = array1;      // NOT ALLOWED

    array2 = array1;             // NOT ALLOWED

HOWEVER, that is not consistent with the definition of the term "lvalue" used by the language spec:

An lvalue is an expression (with an object type other than void) that potentially designates an object [...]

The name “lvalue” comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object “locator value”.

(C17, paragraph 6.3.2.1/1 and footnote 65)

In terms of that definition, array is an lvalue. But it is not a modifiable lvalue.

  • Is the "array" just a name for a block of memory?

Yes, that's a reasonable way to look at it. And quite in line with the above definition of "lvalue".

If it is, where is the address of that block stored?

Why does the address need to be stored anywhere?

int* ptr = array implies that the address of the "array" block has to be stored in the "array", right?

No. It implies that the compiler has to have a way to associate the name array with the storage it represents, so that the compiled program behaves correctly at runtime.

In practice, yes, there needs to be some representation of the location of the array inside the compiled program, but that representation is not part of the C semantics of the program. It is not accessible as a variable, and certainly not from the storage attributed to the array itself. For example, it might exist only as a numeric operand to certain machine instructions.

  • How is it different from [a variable of struct type]? Isn't the "point" also a name for a block of memory?

Yes, "point" is also a name for a block of memory. And in the terminology of the C specs, both your array and your point, where in scope, are lvalues. An array is not particularly different in this regard from an object of any other type. Every object can regarded as a block of storage, and thus, every variable's identifier can be regarded as a name for a block of storage.

  • Related