2

I'm a noob of C++, and I'm tripping about pointers.

An int can express -2147483647 to 2147483647 values, thus 4294967296 total values.

This require 32bit (2^32), thus 4 byte.

I see that if I do a ptr+1 (pointer arithmetic) from a ptr "pointer" to a int, it correctly move of 4 memory addresses (4 byte).

But these "4 byte" are all used to express 4294967296 values.

Where are stored the data that define the type "pointer to int"? I guess the pointer itself should know whick kind of data its pointing, i.e. whick kind of pointer it is. Where are stored these informations? Alongside the address of the pointed data? If I "print" the pointer, I get only the address, not other informations...

Destrif
  • 2,104
  • 1
  • 14
  • 22
markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 1
    Hint: what is the type of your pointer to an int? Look at the declaration of `ptr`, what does it say? – odyss-jii Jul 01 '16 at 09:43
  • 5
    The pointer doesn't know, the compiler does. – Henrik Jul 01 '16 at 09:43
  • if you want size for that pointer just try using sizeof function on that pointer .. – Ankur Jyoti Phukan Jul 01 '16 at 09:45
  • @Henrik: so the compiler keep track of each "pointer" used? :O – markzzz Jul 01 '16 at 09:45
  • 1
    @paizza your C++ code get compiled, so it obviously scans all your code and thus knows each use of a pointer. How does it compile your code when the code says `ptr+1`? `ptr` is a known variable to the compiler, otherwise you would get unknown identifier compile error. So what is the type of `ptr`? – odyss-jii Jul 01 '16 at 09:47
  • Its why you have to declare the pointed to type when you declare a pointer, sothe compiler knows how big the target is. – Galik Jul 01 '16 at 09:48
  • I think this can be usefull http://stackoverflow.com/questions/26976496/what-is-the-data-type-of-pointer-variables – Destrif Jul 01 '16 at 09:53

3 Answers3

2

The compiler has type information available to know how to generate the underlying machine code necessary to evaluate something like ptr + 1. At the machine level it's the equivalent of saying ptr + sizeof(*ptr). So, if you've got code like this:

int *ptr = // some address;
ptr++;

Then the compiler (on x86) will emit something a bit like this for the ptr++:

mov eax,dword ptr [ptr]  ; Load the pointer
add eax,4                ; Add 4 to the address as sizeof(*ptr) is 4
mov dword ptr [ptr],eax  ; Write the new value back

The fact that the compiler has the type information means that the evaluation of ptr + 1 is static, rather than dynamic and can cause you problems when you've got arrays of derived types that you pass by pointer to base types. Take this example:

struct Base
{
  int x;
}; 

struct Derived : Base
{
  int y;
};

void PrintAll(Base *p, int numberOfItems)
{
  while(numberOfItems--)
  {
    std::cout << p->x << std::endl;
    p++; // Oops!!!
  }
}

Derived data[10];
Derived *ptr = data;
PrintAll(ptr, 10);

The line marked "Oops!!!" doesn't work as expected. Although ptr actually points to objects of type Derived it will only actually try to move ptr to point to the next Base rather than Derived as that all the compile time (ie static) information the compiler has available to it. This causes undefined behaviour. If ptr had actually pointed to an array of Base then we'd have been ok. Bugs like this are hard to detect at compile time and this is why you're better of using a container such as std::vector for this sort of thing.

Sean
  • 60,939
  • 11
  • 97
  • 136
2

Firstly, the C standards do not require that an int can represent values outside the rage -32767 to 32767. And there are real-world compilers that do only support a 16-bit int. Compilers are allowed to support a larger range but are not required to.

To answer your question, a declaration of the form

int *x;

tells the compiler that x is a pointer to an int. The compiler itself is implemented with knowledge (either hard-coded, or a configuration option, depending on how the compiler is implemented) about the size of all native types (like int) - and is also implemented to produce that value in any code which uses a sizeof expression (like sizeof(int)). Therefore the compiler can implement pointer arithmetic to suit.

The compiler - since it has parsed and interpreted your code - also knows what type every value and variable has - including pointers and ints.

Printing is another story - printing a pointer prints the address in memory, without the type information, unless you write code to explicitly output the type information as well.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

The compiler knows what the size of int is on the target processor architecture (and in fact, the size of all defined types - even those defined by the user of the compiler).

The compiler decides where to store the increment size of the pointer arithmetic operation of your compiled program. Typically, it could be embedded in the instruction stream.

eerorika
  • 232,697
  • 12
  • 197
  • 326