4

My background is C++ and I'm currently about to start developing in C# so am doing some research. However, in the process I came across something that raised a question about C++.

This C# for C++ developers guide says that

In C++ an array is merely a pointer.

But this StackOverflow question has a highly-upvoted comment that says

Arrays are not pointers. Stop telling people that.

The cplusplus.com page on pointers says that arrays and pointers are related (and mentions implicit conversion, so they're obviously not the same).

The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type.

I'm getting the impression that the Microsoft page wanted to simplify things in order to summarise the differences between C++ and C#, and in the process wrote something that was simpler but not 100% accurate.

But what have arrays got to do with pointers in the first place? Why is the relationship close enough for them to be summarised as the "same" even if they're not?

The cplusplus.com page says that arrays "work like" pointers to their first element. What does that mean, if they're not actually pointers to their first element?

Community
  • 1
  • 1
starsplusplus
  • 1,232
  • 3
  • 19
  • 32
  • What part of this question is not answered by http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c ??? – Chantola Oct 22 '14 at 21:12
  • 1
    This question is more generally conceptual. – Puppy Oct 22 '14 at 21:13
  • 3
    Arrays are not pointers, but you can index pointers as if they were arrays. Arrays also decay to pointers readily. Besides that, function parameters that *look* like arrays are really pointers. So there are plenty of sources of confusion. All or most of this comes from C. – juanchopanza Oct 22 '14 at 21:13
  • 1
    Consider that the type of an array includes the number of elements, and that the size of that type accounts for the total space. – chris Oct 22 '14 at 21:15
  • http://stackoverflow.com/questions/1461432/what-is-array-decaying – Deduplicator Oct 22 '14 at 21:24
  • @juanchopanza: "You can index pointers as if they were arrays." That's actually reversing how things work (though little if any actual difference). Array-indexing is defined by array decay + pointer-arithmetic. – Deduplicator Oct 22 '14 at 21:26
  • @Deduplicator Sure, that is how things work behind the scenes. But at a higher level, it makes perfect sense to index an array, whereas it doesn't always make sense to index a pointer. Pointers represent too many things in C and C++. – juanchopanza Oct 22 '14 at 21:34
  • @Deduplicator Thanks for the link. I disagree with the duplicate vote because the answers to that question assume you already know when/where array decaying happens and want to know how it works. However, reading between the lines, I may have discovered (part of) the answer. Is the relationship between the two simply that arrays and pointers are distinct, but that arrays function as pointers when they are passed to a function? – starsplusplus Oct 22 '14 at 21:37
  • @starsplusplus: The relationship is that arrays in nearly all contexts decay to rvalue-pointers to their first element (exceptions `sizeof`, `_Alignot`, `&`). Plus some confusion regarding function prototypes (looks like an array-parameter but is actually a pointer parameter). – Deduplicator Oct 22 '14 at 21:40
  • 1
    @starsplusplus It is a bit more complicated than that. Arrays can decay to pointers. But you can also pass arrays by reference to a function. In this case, there is no decay to pointer. You can also pass pointers to arrays. In both cases, the size information is kept. Arrays function as pointers when passed to functions *that expect pointers*. – juanchopanza Oct 22 '14 at 21:42
  • @juanchopanza Thanks; that's helpful. – starsplusplus Oct 22 '14 at 21:43
  • I think some of the relationship between arrays and pointers can be explained when looking at the history of C; see http://stackoverflow.com/a/7073322 – dyp Oct 22 '14 at 21:45

6 Answers6

4

There is a lot of bad writing out there. For example the statement:

In C++ an array is merely a pointer.

is simply false. How can such bad writing come about? We can only speculate, but one possible theory is that the author learned C++ by trial and error using a compiler, and formed a faulty mental model of C++ based on the results of his experiments. This is possibly because the syntax used by C++ for arrays is unconventional.

The next question is, how can a learner know if he/she is reading good material or bad material? Other than by reading my posts of course ;-) , participating in communities like Stack Overflow helps to bring you into contact with a lot of different presentations and descriptions, and then after a while you have enough information and experience to make your own decisions about which writing is good and which is bad.

Moving back to the array/pointer topic: my advice would be to first build up a correct mental model of how object storage works when we are working in C++. It's probably too much to write about just for this post, but here is how I would build up to it from scratch:

  • C and C++ are designed in terms of an abstract memory model, however in most cases this translates directly to the memory model provided by your system's OS or an even lower layer
  • The memory is divided up into basic units called bytes (usually 8 bits)
  • Memory can be allocated as storage for an object; e.g. when you write int x; it is decided that a particular block of adjacent bytes is set aside to store an integer value. An object is any region of allocated storage. (Yes this is a slightly circular definition!)
  • Each byte of allocated storage has an address which is a token (usually representible as a simple number) that can be used to find that byte in memory. The addresses of any bytes within an object must be sequential.
  • The name x only exists during the compilation stage of a program. At runtime there can be int objects allocated that never had a name; and there can be other int objects with one or more names during compilation.
  • All of this applies to objects of any other type, not just int
  • An array is an object which consists of many adjacent sub-objects of the same type
  • A pointer is an object which serves as a token identifying where another object can be found.

From hereon in, C++ syntax comes into it. C++'s type system uses strong typing which means that each object has a type. The type system extends to pointers. In almost all situations, the storage used to store a pointer only saves the address of the first byte of the object being pointed to; and the type system is used at compilation time to keep track of what is being pointed to. This is why we have different types of pointer (e.g. int *, float *) despite the fact that the storage may consist of the same sort of address in both cases.


Finally: the so-called "array-pointer equivalence" is not an equivalence of storage, if you understood my last two bullet points. It's an equivalence of syntax for looking up members of an array.

Since we know that a pointer can be used to find another object; and an array is a series of many adjacent objects; then we can work with the array by working with a pointer to that array's first element. The equivalence is that the same processing can be used for both of the following:

  • Find Nth element of an array
  • Find Nth object in memory after the one we're looking at

and furthermore, those concepts can be both expressed using the same syntax.

M.M
  • 138,810
  • 21
  • 208
  • 365
2

They are most definitely not the same thing at all, but in this case, confusion can be forgiven because the language semantics are ... flexible and intended for the maximum confusion.

Let's start by simply defining a pointer and an array.

A pointer (to a type T) points to a memory space which holds at least one T (assuming non-null).

An array is a memory space that holds multiple Ts.

A pointer points to memory, and an array is memory, so you can point inside or to an array. Since you can do this, pointers offer many array-like operations. Essentially, you can index any pointer on the presumption that it actually points to memory for more than one T.

Therefore, there's some semantic overlap between (pointer to) "Memory space for some Ts" and "Points to a memory space for some Ts". This is true in any language- including C#. The main difference is that they don't allow you to simply assume that your T reference actually refers to a space where more than one T lives, whereas C++ will allow you to do that.

Since all pointers to a T can be pointers to an array of T of arbitrary size, you can treat pointers to an array and pointers to a T interchangably. The special case of a pointer to the first element is that the "some Ts" for the pointer and "some Ts" for the array are equal. That is, a pointer to the first element yields a pointer to N Ts (for an array of size N) and a pointer to the array yields ... a pointer to N Ts, where N is equal.

Normally, this is just interesting memory crapping-around that nobody sane would try to do. But the language actively encourages it by converting the array to the pointer to the first element at every opportunity, and in some cases where you ask for an array, it actually gives you a pointer instead. This is most confusing when you want to actually use the array like a value, for example, to assign to it or pass it around by value, when the language insists that you treat it as a pointer value.

Ultimately, all you really need to know about C++ (and C) native arrays is, don't use them, pointers to arrays have some symmetries with pointers to values at the most fundamental "memory as an array of bytes" kind of level, and the language exposes this in the most confusing, unintuitive and inconsistent way imaginable. So unless you're hot on learning implementation details nobody should have to know, then use std::array, which behaves in a totally consistent, very sane way and just like every other type in C++. C# gets this right by simply not exposing this symmetry to you (because nobody needs to use it, give or take).

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • A pointer to a type need not point to at least one object of the type. – Deduplicator Oct 22 '14 at 21:37
  • 1
    *"you can treat pointers to an array and pointers to a T interchangably"* Do you mean true pointer-to-array types, or pointers that point to elements of an array? – dyp Oct 22 '14 at 21:38
  • To add to the confusion, a pointer to an array is a different thing than a pointer to an *element* of an array. – juanchopanza Oct 22 '14 at 21:38
  • @Deduplicator: I don't recall the exact Standard wording, but simply forming some kinds of invalid pointers is UB right away, even if you don't de-ref them, IIRC. All the legal aliasing stuff just confuses what "object" and "type" actually mean in this respect. – Puppy Oct 22 '14 at 21:41
  • @dyp: Pointers that point to elements of an array. Pointer-to-array types are interchangable as long as you don't index them :P – Puppy Oct 22 '14 at 21:43
1

Arrays and pointers in C and C++ can be used with the exact same semantics and syntax in the vast majority of cases.

That is achieved by one feature:

Arrays decay to pointers to their first element in nearly all contexts.
Exceptions in C: sizeof, _Alignas, _Alignas, address-of &
In C++, the difference can also be important for overload-resolution.

In addition, array notation for function arguments is deceptive, these function-declarations are equivalent:

int f(int* a);
int f(int a[]);
int f(int a[3]);

But not to this one:

int f(int (&a)[3]);
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
1

Besides what has already been told, there is one big difference: pointers are variables to store memory addresses, and they can be incremented or decremented and the values they store can change (they can point to any other memory location). That's not the same for arrays; once they are allocated, you can't change the memory region they reference, e.g. you cannot assign other values to them:

int my_array[10];
int x = 2;

my_array = &x;
my_array++;

Whereas you can do the same with a pointer:

int *p = array;
p++;
p = &x;
Samir Aguiar
  • 2,509
  • 2
  • 18
  • 32
0

The meaning in this guide was simply that in C# an array is an object (perhaps like in STL that we can use in C++), while in C++ an array is basically a sequence of variables located & allocated one after the other, and that's why we can refer to them using a pointer (pointer++ will give us the next one etc.).

user265732
  • 585
  • 4
  • 14
  • An array is an object in C++ too. Whatever gave you the idea it isn't? It consists of consecutive sub-objects of the arrays element-type, but that does not detract from its objects-ness in the least. – Deduplicator Oct 22 '14 at 23:08
  • 1
    Well I don't know your definition for an object, but for me an object is an instance of a class, that I can use in the OOP way: Inherit from it, overload operators and methods etc. Declaring 'int arr[10];', 'arr' is a pointer after all, it points to the address of the first element. it doesn't have methods or data members. So saying that an array is a pointer is not very correct, but the way I see it, it's definitely not an object either. – user265732 Oct 22 '14 at 23:18
  • First, an `int` is not an object according to your definition. I doubt you wanted that. And if you allow `int` being an object, your objections to arrays being objects becomes really flimsy. In the end, use the C++-definitions when talking C++. – Deduplicator Oct 23 '14 at 00:42
  • From the above mentioned guide: "In C#, arrays are objects that include methods and properties. For example, the size of an array can be queried via the Length property." The meaning of an object here is something that I can refer to as one entity, for example- "tell" the array to sort itself, get the max element etc.. An int, for example, does have operators and so on, so I can do: int a(1),b(2); a+b;// sums up 1+2 But: int arr1[10], arr2[10]; arr1+arr2; //some address - not a new array – user265732 Oct 23 '14 at 06:56
  • So? A C++-object need not have any methods and properties, `int` does not after all. Also, you can refer to an array as one entity/object, even if your options for doing something with it are rather limited. – Deduplicator Oct 23 '14 at 08:31
  • 1
    But - in the guide, the term "Object" refers to the OOP consept, you can't compare two languages by using the terms of one of them. So, OOP speaking, an array is conseptually not an object. Saying it is a C++ object is fine, but it has nothing to do with the OOP's definition of an object. In my opinion anyway. – user265732 Oct 23 '14 at 09:12
  • FYI, OOP means 50 different things to 30 different people. "You can'T compare two languages using the terms of one of them" So far, so fair. The one who gets to determine the terms will always win. You don't follow that truth though, instead swallowing the C#-line hook, bait and sinker. – Deduplicator Oct 23 '14 at 09:16
  • Anyway, my point is- there is something in what they say, even if it doesn't exactly fit into the C++ semantic meaning of an object. – user265732 Oct 23 '14 at 09:30
  • Of course the C++-concept is not identical to the C#-concept, both fall short if measured by the others standards (which stress their advantages and ignore their disadvantages). Still, you can build the C#-equivalent in C++ easily, but not the C++-equivalent in C#. – Deduplicator Oct 23 '14 at 09:37
  • I agree with your last line. I'm not saying that C# is "better" than C or anything. I am giving my interpretation to why does the above discussed line is correct in some manner. – user265732 Oct 23 '14 at 11:04
  • @Deduplicator `int`s aren't objects in C++, though. Only in languages like Java (and maybe C# too) where *everything*'s an object. – starsplusplus Oct 23 '14 at 13:16
  • In Java an int is not considered as an object, Integer is. – user265732 Oct 23 '14 at 13:19
  • @starsplusplus: You obviously never read the standard if you think that. – Deduplicator Oct 23 '14 at 13:30
  • @Deduplicator Meh. You are technically correct, but that's not how most C++ programmers use the word in my experience. Further, the top answer for [What is a class and object in C++?](http://stackoverflow.com/questions/1093968/what-is-a-class-and-object-in-c) on SO is "an object is an instance of a class". – starsplusplus Oct 23 '14 at 14:39
  • @starsplusplus: Sometimes even programmers ignore half what they speak about to have a catchier phrase... – Deduplicator Oct 23 '14 at 16:26
  • The standard C++ terminology for user265732's "object" is "object of class type" – M.M Feb 12 '17 at 23:19
-1

it's as simple as:

int arr[10];

int* arr_pointer1 = arr;
int* arr_pointer2 = &arr[0];

so, since arrays are contiguous in memory, writing

arr[1];

is the same as writing:

*(arr_pointer+1)

pushing things a bit further, writing:

arr[2];
//resolves to
*(arr+2);
//note also that this is perfectly valid 
2[arr];
//resolves to
*(2+arr);
dau_sama
  • 4,247
  • 2
  • 23
  • 30