Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is arr and &arr the same?

Tags:

c++

c

pointers

I have been programming c/c++ for many years, but todays accidental discovery made me somewhat curious... Why does both outputs produce the same result in the code below? (arr is of course the address of arr[0], i.e. a pointer to arr[0]. I would have expected &arr to be the adress of that pointer, but it has the same value as arr)

  int arr[3];
  cout << arr << endl;
  cout << &arr << endl;

Remark: This question was closed, but now it is opened again. (Thanks ?)

I know that &arr[0] and arr evaluates to the same number, but that is not my question! The question is why &arr and arr evaluates to the same number. If arr is a literal (not stored anyware), then the compiler should complain and say that arr is not an lvalue. If the address of the arr is stored somewhere then &arr should give me the address of that location. (but this is not the case)

if I write

const int* arr2 = arr;

then arr2[i]==arr[i] for any integer i, but &arr2 != arr.

like image 575
ragnarius Avatar asked Jan 18 '12 20:01

ragnarius


People also ask

What is ARR and why is it important?

Annual Recurring Revenue, or ARR, is a Subscription Economy® metric that shows the money that comes in every year for the life of a subscription (or contract). More specifically, ARR is the value of the recurring revenue of a business's term subscriptions normalized for a single calendar year.

Why is revenue lower than ARR?

When calculating Annual Recurring Revenue, we would not typically expect the total to be higher than revenue, overall. This is because the revenue considered in ARR is specifically subscription or contract based.

Why is ARR a good metric?

Quantifies the company's growth The predictability and stability of ARR make the metric a good measure of a company's growth. By comparing ARRs for several years, a company can clearly see whether its business decisions are resulting in any progress.

Why is ARR important SaaS?

The power of understanding ARR should not be underestimated by SaaS businesses. Having this information not only helps you monitor the company's overall health but can also reveal which decisions are having a positive or negative impact and influence your long-term strategies.


6 Answers

#include <cassert>

struct foo {
    int x;
    int y;
};

int main() {    
    foo f;
    void* a = &f.x;
    void* b = &f;
    assert(a == b);
}

For the same reason the two addresses a and b above are the same. The address of an object is the same as the address of its first member (Their types however, are different).

                            arr
                      _______^_______
                     /               \
                    | [0]   [1]   [2] |
--------------------+-----+-----+-----+--------------------------
      some memory   |     |     |     |        more memory
--------------------+-----+-----+-----+--------------------------
                    ^
                    |
           the pointers point here

As you can see in this diagram, the first element of the array is at the same address as the array itself.

like image 50
R. Martinho Fernandes Avatar answered Oct 11 '22 15:10

R. Martinho Fernandes


They're not the same. They just are at the same memory location. For example, you can write arr+2 to get the address of arr[2], but not (&arr)+2 to do the same.

Also, sizeof arr and sizeof &arr are different.

like image 44
Mr Lister Avatar answered Oct 11 '22 14:10

Mr Lister


The two have the same value but different types.

When it's used by itself (not the operand of & or sizeof), arr evaluates to a pointer to int holding the address of the first int in the array. &arr evaluates to a pointer to array of three ints, holding the address of the array. Since the first int in the array has to be at the very beginning of the array, those addresses must be equal.

The difference between the two becomes apparent if you do some math on the results:

arr+1 will be equal to arr + sizeof(int).

((&arr) + 1) will be equal to arr + sizeof(arr) == arr + sizeof(int) * 3

Edit: As to how/why this happens, the answer is fairly simple: because the standard says so. In particular, it says (§6.3.2.1/3):

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

[note: this particular quote is from the C99 standard, but I believe there's equivalent language in all versions of both the C and C++ standards].

In the first case (arr by itself), arr is not being used as the operand of sizeof, unary &, etc., so it is converted (not promoted) to the type "pointer to type" (in this case, "pointer to int").

In the second case (&arr), the name obviously is being used as the operand of the unary & operator -- so that conversion does not take place.

like image 37
Jerry Coffin Avatar answered Oct 11 '22 14:10

Jerry Coffin


The address is the same but both expressions are different. They just start at the same memory location. The types of both expressions are different.

The value of arr is of type int * and the value of &arr is of type int (*)[3].

& is the address operator and the address of an object is a pointer to that object. The pointer to an object of type int [3] is of type int (*)[3]

like image 38
ouah Avatar answered Oct 11 '22 14:10

ouah


They are not the same.

A bit more strict explanation:

arr is an lvalue of type int [3]. An attempt to use arr in some expressions like cout << arr will result in lvalue-to-rvalue conversion which, as there are no rvalues of array type, will convert it to an rvalue of type int * and with the value equal to &arr[0]. This is what you can display.

&arr is an rvalue of type int (*)[3], pointing to the array object itself. No magic here :-) This pointer points to the same address as &arr[0] because the array object and its first member start in the exact same place in the memory. That's why you have the same result when printing them.


An easy way to confirm that they are different is comparing *(arr) and *(&arr): the first is an lvalue of type int and the second is an lvalue of type int[3].

like image 36
Kos Avatar answered Oct 11 '22 15:10

Kos


Pointers and arrays can often be treated identically, but there are differences. A pointer does have a memory location, so you can take the address of a pointer. But an array has nothing pointing to it, at runtime. So taking the address of an array is, to the compiler, syntactically defined to be the same as the address of the first element. Which makes sense, reading that sentence aloud.

like image 37
Graham Perks Avatar answered Oct 11 '22 14:10

Graham Perks