2

For example:

int *p;
int a[2] = {1, 2};
p1 = a;

I was wondering where does c++ store the information of memory space of each element? I mean, when I do this:

cout << p << endl;

I only can get the memory address of that array, there is obviously no information related to the "memory length" of single element. But I think there should be some place that the language can refer to the space of memory space of each element. Since if I go on the call this:

cout << *++p << endl;

I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.

So, again, my question is: Where is the information of the memory space of element in that array stored? Or is there something like "\0" at the end of each element to signify the end of one element in that array, so the *++p is about to get to the next right place?

jww
  • 97,681
  • 90
  • 411
  • 885
Z_J
  • 125
  • 1
  • 11
  • 4
    It isn't stored; it is handled by the compiler. – Gareth Mar 23 '15 at 15:35
  • This answer to this question (with respect to allocation/deallocation and actually tracking the memory, vs. just incrementing by `sizeof` the elements when you do array indexing) is *incredibly* implementation dependent. For a bit of background on it, you could read [this question](http://stackoverflow.com/questions/24203940/why-does-free-in-c-not-take-the-number-of-bytes-to-be-freed/24222002#24222002) about why `malloc/free` don't take size parameters. Basically, consider it magic unless you really need to know. – aruisdante Mar 23 '15 at 15:35
  • @aruisdante Thanks for your comment and the information in it! I know it's magic, and there are lots of magic happening there. But I'm just deadly curious about this one :) – Z_J Mar 23 '15 at 15:52

3 Answers3

6

where does the information of memory space of each element of that array store?

When you use:

int *p;
int a[2] = {1, 2};
p = a;

memory for the elements of a are in the stack. They memory is contiguous. p points to the first element of a.

Regarding:

I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.

Yes, that is correct.

From a purely numerical point of view,

p+1 == p + sizeof(*p)

sizeof(*p) can be computed at compile time. There is no need for any run time information. There is no need for markers to signify the end of an element.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Did you mean `p+1` or `p`? – David G Mar 23 '15 at 15:40
  • I remember back in the day they used to teach arrays by having us manually implement a method which given a byte-wise view on an array would calculate the correct address for an index for one and two dimensional arrays. Was a very good way of learning what the compiler is doing under the hood. – aruisdante Mar 23 '15 at 15:40
  • @0x499602D2, I meant to use `p+1` but I meant to use `==` instead of `=`. – R Sahu Mar 23 '15 at 15:42
  • Thanks! The `p+1 = p + sizeof(*p)` explanation is a good way of making me comfortable with this question. And as someone said in the comment, it's implementation dependent. So, can I understand that as there are many kind of implementations of the "overloaded operation" like "+, -, ++, --" for pointers with respect to different systems in which `p+1 = p + sizeof(*p)` is a possible implementation? – Z_J Mar 23 '15 at 15:48
  • @ZongyaoJin The actual array indexing isn't really implementation dependent; in any implementation I've ever seen they're always allocated in contiguous memory, so it's always `p + sizeof(*p)`. What `sizeof` returns for any particular type is certainly platform dependent however. – aruisdante Mar 23 '15 at 15:54
3

The memory in an array is contiguous, so yes incrementing a pointer will get you from one element to the next element.

The way that it knows how far in memory to go to get to the next element is by the type of the pointer, in this case it is an int*, so it knows to increment by sizeof(int) to get to the next element.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
0

It doesn't. C++ has no runtime information about the types of variables. It simply interprets the data behind the pointer as the type you gave to it in your source code. Take the following code for example:

void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }

int i = 9;
int * p = &i;

f(p);

This will print Integerpointer because the compiler knows at compile time that the type of p is int *. The following code will print Charpointer because the type is changed (the compiler interprets the pointer different):

void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }

int i = 9;
int * p = &i;

f(reinterpret_cast<char *>(p));

The compiler substitutes f() with the matching function call in your source code. So the interpretation of the underlying data is done at compiletime.

To address your array question: The compiler knows the sizes of the elements at compile time. It then adjusts the pointer addition when accessing the elements and puts the size hard coded in your machine code. If you know a bit assambly you can look at the assambly code and see this effect.

Otomo
  • 880
  • 7
  • 12