1

!!The question is a little long, so I divided it into 4 parts, so that the reader would not be distracted!! I got a piece of information recently, that the name of the array in C/C++ is a pointer to the first element in the array, and that was from an AI (Chat GPT 3.5 and 4) and my tutor at university. And when I was looking at the memory locations for each of the pointer (the name of the array) and the first element and the address stored in the pointer, I found that they are all equal.

#include<iostream>
using namespace std;
int main (){
  int arr[3]{1,2,3};
  cout << &(arr)   <<"   "<<&arr[0]  <<"   "<< arr  <<endl;
  return 0;
}
/*
Output:
0x69fee0   0x69fee0   0x69fee0
*/

And here lies the first point or problem, how is the address of the pointer equal to the address that the pointer stores, as if we say a pointer points to itself and this will become an endless loop.

When I searched for the answer to this question, I found some specialists saying that the name of the matrix is not an indicator at all. Here is the second point.

When I searched more and more, I found an answer that says: It is true that the pointer has the same address followed by its value, but this does not mean that the pointer is located in the same memory space, He said that the bit space varies, which is inferred by the following program:

#include<iostream>
using namespace std;
int main (){
  int arr[3]{1,2,3};
  cout << &(arr)   <<"   "<<&arr[0]  <<"   "<< arr  <<endl;
  cout << &(arr)+1 <<"   "<<&arr[0]+1<<"   "<< arr+1<<endl;
  cout << &(arr)+2 <<"   "<<&arr[0]+2<<"   "<< arr+2<<endl;
  cout << &(arr)+3 <<"   "<<&arr[0]+3<<"   "<< arr+3<<endl;
  cout << sizeof(arr) <<"   "<<sizeof(&arr[0])<<"   "<< sizeof(&arr)<<endl;
  return 0;
}ٍ
/*
Output:
0x69fee0   0x69fee0   0x69fee0
0x69feec   0x69fee4   0x69fee4
0x69fef8   0x69fee8   0x69fee8
0x69ff04   0x69feec   0x69feec
12   4   4
*/

And This was the third point.

Regarding the fourth and most important point: It is that I deduced the shape of the memory through the outputs of the previous program, as we do in the science of logical circuits deducing the circuit through the outputs. And I want you to see if the drawing (unscientific, but to bring the idea closer) is correct in its general idea, and any comments on it are very important to me, because I am really interested in how the memory will look in the event that the name of the matrix is a pointer. Finally, when you see the drawing, there is an important question: Is the memory in the RAM really divided into two halves, as shown in the drawing? Which half of the pointer and half of the matrix, and if that is true, what is the mechanism?

diagram : The picture shows the divisions of the ram in the form of a list of boxes, and the picture shows how this drawing concluded that through the arrows directed on each section, and it expresses an already written output process.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
  • `&(arr)` is not the name of the array, `arr` is the name of the array. – john May 16 '23 at 13:38
  • 6
    _"I got a piece of information recently, that the name of the array in C/C++ is a pointer to the first element in the array"_ You got bad information. An array **is not** a pointer. It seems that all or most of this question is based on that bad information. – Drew Dormann May 16 '23 at 13:38
  • The name of an array is **not** a pointer. It can decay into a pointer to the first element in the array, but that doesn't make it a pointer. – NathanOliver May 16 '23 at 13:39
  • 2
    `&(arr)` and `arr` are different things, although when printed as pointers they have the same value. The difference is the **type**, and this explain the difference you see what you start comparing `&(arr)+1` with `&arr[1]` – john May 16 '23 at 13:41
  • 1
    [What is array to pointer decay?](https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay) – Drew Dormann May 16 '23 at 13:43
  • 2
    Your lied to you. It's not the 's fault, because they just regurgitate convincing word salad with confidence. In order to ascertain if the results are correct you need to be a domain expert so you can assess the fidelity of the response. – Eljay May 16 '23 at 13:43
  • I having some trouble following your argument, but it seems to me that you've made a mistake right at the start (that you think arrays and pointers are the same thing), and then you've done a lot of reasoning based on that mistake. You are making a fairly simple thing very complicated. I suggest you find a good C++ book that explains this instead of trying to research and reason it out for yourself. – john May 16 '23 at 13:44
  • No memory is not divided into two halves. Arrays are stored in the simplest way possible, as contiguous data in unified memory. – john May 16 '23 at 13:48
  • @DrewDormann if you think it's a duplicate, why don't you close it as a duplicate? – Thomas Weller May 16 '23 at 13:51
  • @ThomasWeller I'm not certain, and my vote would close it entirely. So I'm allowing the community to decide. – Drew Dormann May 16 '23 at 13:53
  • Raw arrays and pointers are distinct but related types. Arrays used to be classified as **by-reference** (≠ **by-value**) undec C programming language; C just lacked the reference type present in C++, and passing arrays by value seemed irrational back then. The official term in modern docs is **"decay"**. Raw arrays **decay** to pointers. It is a much stronger conversion - in tems of syntax - than implicit casting. – Red.Wave May 16 '23 at 13:56
  • You should compile this as 64 bit and also `cout << sizeof(arr[0])`. – Thomas Weller May 16 '23 at 14:25
  • @Red.Wave: Pointer decay is a category of implicit conversion (There is by definition no such thing as implicit casting). Not sure what you mean by "stronger" conversion, usually I think that means "more powerful, capable of forming relationships between more types", but the pointer decay conversion is quite narrow and only relates types safely, so I would not categorize it as "strong". – Ben Voigt May 16 '23 at 15:19
  • @BenVoigt Formal definitions are to comlicated, if precise terms are involved. There's no formal definition for strong in this context. But decaying is more than just implicit conversion. What happens when a function takes a argument of array type?! I cannot describe it as implicit conversion; the type is totally replaced with a pointer. If decaying was a mere implicit conversion, then a new term would not be needed. Therefore I was hesitant to just call it a coversion. – Red.Wave May 16 '23 at 16:40
  • @Red.Wave: Ahh yes, adjustment of parameter types. https://eel.is/c++draft/dcl.fct#5 But that is not any type of cast or conversion at all, and also has nothing to do with decay. – Ben Voigt May 16 '23 at 16:44
  • @BenVoigt Then I need an example of decaying type with no parameter adjustment. Otherwise what's the point of introduing decay as just a synonym for conversion?! Either decay is considered more generic, or more specific. In either case, without parameter type replacement, it would be pointless. – Red.Wave May 16 '23 at 17:14
  • @Red.Wave: "Array-to-pointer conversion" is the official term. It's one of many categories of conversion. https://eel.is/c++draft/conv#array – Ben Voigt May 16 '23 at 18:40
  • @BenVoigt what makes raw arrays different from other types is decaying. That's the focus of the problem, and only valid because of the argument type replacement. Note the difference from implicit conversion. Every raw pointer implicitly converts to `void*`; they just **do not decay** to `void*`, because the atomatic type replacement never takes place. – Red.Wave May 17 '23 at 09:26
  • @Red.Wave You are correct that array-to-pointer conversion is a different conversion from pointer-to-superclass-pointer conversion. And array-to-pointer type adjustment (for function signatures) definitely exists, but it isn't happening in this question, so I disagree that it is "the focus of the problem" OP is asking about. The `ostream` member and friend `operator<<` functions being used here were declared with pointers in the first place, their parameter lists have not been adjusted. – Ben Voigt May 17 '23 at 14:27
  • @BenVoigt ***"the name of the array in C/C++ is a pointer to the first element in the array"***. That essentially means the OP needs a clearance on the difference between raw arrays and other types. The confusion about raw pointers and raw arrays can only be removed, if decaying and argument replacement are explained correctly. A simple to understand explanation would be the true answer. Anything else is a distraction and confusion. – Red.Wave May 17 '23 at 14:41

2 Answers2

1

arr, &arr[0] and &arr will have the same value:

  • arr printed value is the (implicit address of the) array
  • &arr printed value is the explicit address of the array.
  • &arr[0] printed value the address of the first element of the array, which is the same as the address of the array

But when the index is different:

  • arr is an array of three integers.
  • arr + 1 is the address of the array plus sizeof(int) it is the same as &arr[1]
  • &arr + 1 is the address of the array + sizeof(arr) in our case it is equivalent to arr+3, it is the same as (&arr)[1]
SHR
  • 7,940
  • 9
  • 38
  • 57
0

Beware of the types!

First, may be many of the expressions have the same value, but not of the same type; 1 orange is not 1 banana.

Second, there is no pointer there, only addresses. A pointer is a variable in which you can store an address. An address is a (typed) value. A pointer is a (typed) storage.

arr is the array (of type int[3], i.e. sizeof(arr)==3*sizeof(int)), not a pointer to the first element of the array. If it had been a pointer you would have been able to write arr++, or arr = p(for some other pointer int *p) which is forbidden. arr is the array, just like i is an int in int i (i is not a pointer right?). typeid(arr).name() would give something like A3_i (array of three ints).

&arr is the address of the array. If you make arithmetic with that address, then it is in terms of sizeof(arr). (&arr)+1 (or &arr+1) is the address just after the (whole) array arr. typeid(&arr).name() would give something like PA3_i(pointer to array of three ints).

&(arr[0]) (or &arr[0]) is the address of the first element of arr then an address of type int *. typeid(&arr[0]).name() would give Pi (pointer to int).

Now arrays can decay to pointers in many contexts (argument passing, pointer assignment, pointer arithmetic, ...). That means that arr can be viewed as the address of its first element, i.e. arr is viewed as &arr[0] so as an int *. For example, you can write int *p = arr or arr+1. That doesn't mean that arr is a pointer, just that in this context arr is considered as the address of its first element. Remark that it is exactly the case when you make cout << arr (arr decays as you saw an address not an array...).

Note that array can decay to pointer... is somehow misleading, it should have been much better to say array decay to address... (IMHO).

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
  • "A pointer is a variable in which you can store an address." Not exactly. You can have lvalues of pointer type and also rvalues of pointer type. "An address is a (typed) value." No. "A pointer is a (typed) storage." No. A pointer is an object whose type is a pointer type and whose value is a memory address. – Ben Voigt May 16 '23 at 15:15
  • Also, "an array lvalue can decay to a pointer rvalue" is correct. If you rewrite it as "an array decays to an address", you have violated your own good advice "Beware of the types", because the difference between a pointer rvalue and an address is -- the pointer has a type besides the address which is its value. – Ben Voigt May 16 '23 at 15:17
  • @BenVoigt You can have lvalues of pointer type because a pointer is a storage (an object if you prefer). You can have rvalues of pointer type because a pointer is a storage (an object) that contains an address (a memory address if you prefer)! No? – Jean-Baptiste Yunès May 16 '23 at 15:27
  • You can have lvalues of pointer type, but pointer decay never creates one. A pointer lvalue, for example a variable of pointer type, is associated with storage (you can assign a different address of proper pointer type into it). But not every pointer value is an lvalue. It's not clear to me whether when you say "a pointer is a storage" whether you are talking about storing the address in the pointer, or following the address to find another object, but the statement is not true in either case. (Counterexample to first interpretation: pointer rvalue. – Ben Voigt May 16 '23 at 15:40
  • @BenVoigt Aren't all values typed? Wasn't what means rvalue??? lvalues necessarily correspond to a storage, not rvalues... – Jean-Baptiste Yunès May 16 '23 at 15:40
  • Counterexamples to second interpretation: null pointers, having multiple pointers to the same object) – Ben Voigt May 16 '23 at 15:40
  • @BenVoigt When I say "a pointer is a variable", wasn't it clear? I mean `int *p`, `p` is a (typed) storage, that's all (is it something else?). What are the values stored in a pointer? Addresses (typed) (or what?). > – Jean-Baptiste Yunès May 16 '23 at 15:45
  • An address doesn't have type. You may argue that makes an address "not a value" in the C++ sense of the word "value". If you have an object `int x;` then `&x` and `reinterpret_cast(&x)` are pointer rvalues with different type and the same address. Neither of those two pointers owns any storage, `x` owns the storage. Neither of those two pointers is a variable. (Variables with pointer type are variables, but pointer rvalues are not variables, so "every pointer is a variable" is a false claim) – Ben Voigt May 16 '23 at 15:46
  • An rvalue carries a value (which in the case of a pointer rvalue is an address), but it has no storage. That's why you cannot, for example, write `&&x`, while you can make a pointer variable (which is an lvalue) `int* p = &x;` and it does have storage, so `&p` works. – Ben Voigt May 16 '23 at 15:50