Why does pointer arithmetic work the way it does? [duplicate] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Does anyone have any good articles or explanations (blogs, examples) for pointer arithmetic? Figure the audience is a bunch of Java programmers learning C and C++.

Here is where I learned pointers: http://www.cplusplus.com/doc/tutorial/pointers.html
Once you understand pointers, pointer arithmetic is easy. The only difference between it and regular arithmetic is that the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. For example, if you have a pointer to an int and an int's size is 4 bytes, (pointer_to_int + 4) will evaluate to a memory address 16 bytes (4 ints) ahead.
So when you write
(a_pointer + a_number)
in pointer arithmetic, what's really happening is
(a_pointer + (a_number * sizeof(*a_pointer)))
in regular arithmetic.

First, the binky video may help. It's a nice video about pointers. For arithmetic, here is an example:
int * pa = NULL;
int * pb = NULL;
pa += 1; // pa++. behind the scenes, add sizeof(int) bytes
assert((pa - pb) == 1);
print_out(pa); // possibly outputs 0x4
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(Note that incrementing a pointer that contains a null pointer value strictly is undefined behavior. We used NULL because we were only interested in the value of the pointer. Normally, only use increment/decrement when pointing to elements of an array).
The following shows two important concepts
addition/subtraction of a integer to a pointer means move the pointer forward / backward by N elements. So if an int is 4 bytes big, pa could contain 0x4 on our platform after having incremented by 1.
subtraction of a pointer by another pointer means getting their distance, measured by elements. So subtracting pb from pa will yield 1, since they have one element distance.
On a practical example. Suppose you write a function and people provide you with an start and end pointer (very common thing in C++):
void mutate_them(int *begin, int *end) {
// get the amount of elements
ptrdiff_t n = end - begin;
// allocate space for n elements to do something...
// then iterate. increment begin until it hits end
while(begin != end) {
// do something
begin++;
}
}
ptrdiff_t is what is the type of (end - begin). It may be a synonym for "int" for some compiler, but may be another type for another one. One cannot know, so one chooses the generic typedef ptrdiff_t.

applying NLP, call it address arithmetic. 'pointers' are feared and misunderstood mostly because they are taught by the wrong people and/or at the wrong stage with wrong examples in the wrong way. It is no wonder that nobody 'gets' it.
when teaching pointers, the faculty goes on about "p is a pointer to a, the value of p is the address of a" and so on. it just wont work. here is the raw material for you to build with. practice with it and your students will get it.
'int a', a is an integer, it stores integer type values.
'int* p', p is an 'int star', it stores 'int star' type values.
'a' is how you get the 'what' integer stored in a (try not to use 'value of a')
'&a' is how you get the 'where' a itself is stored (try to say 'address')
'b = a' for this to work, both sides must be of the same type. if a is int, b must be capable of storing an int. (so ______ b, the blank is filled with 'int')
'p = &a' for this to work, both sides must be of the same type. if a is an integer, &a is an address, p must be capable of storing addresses of integers. (so ______ p, the blank is filled with 'int *')
now write int *p differently to bring out the type information:
int* | p
what is 'p'? ans: it is 'int *'. so 'p' is an address of an integer.
int | *p
what is '*p'? ans: it is an 'int'. so '*p' is an integer.
now on to the address arithmetic:
int a;
a=1;
a=a+1;
what are we doing in 'a=a+1'? think of it as 'next'. Because a is a number, this is like saying 'next number'. Since a holds 1, saying 'next' will make it 2.
// fallacious example. you have been warned!!!
int *p
int a;
p = &a;
p=p+1;
what are we doing in 'p=p+1'? it is still saying 'next'. This time, p is not a number but an address. So what we are saying is 'next address'. Next address depends on the data type, more specifically on the size of the data type.
printf("%d %d %d", sizeof(char), sizeof(int), sizeof(float));
so 'next' for an address will move forward sizeof(data type).
this has worked for me and all of the people I used to teach.

I consider a good example of pointer arithmetic the following string length function:
int length(char *s)
{
char *str = s;
while(*str++);
return str - s;
}

So, the key thing to remember is that a pointer is just a word-sized variable that's typed for dereferencing. That means that whether it's a void *, int *, long long **, it's still just a word sized variable. The difference between these types is what the compiler considers the dereferenced type. Just to clarify, word sized means width of a virtual address. If you don't know what this means, just remember on a 64-bit machine, pointers are 8 bytes, and on a 32-bit machine, pointers are 4 bytes. The concept of an address is SUPER important in understanding pointers. An address is a number capable of uniquely identifying a certain location in memory. Everything in memory has an address. For our purposes, we can say that every variable has an address. This isn't necessarily always true, but the compiler lets us assume this. The address itself is byte granular, meaning 0x0000000 specifies the beginning of memory, and 0x00000001 is one byte into memory. This means that by adding one to a pointer, we're moving one byte forward into memory. Now, lets take arrays. If you create an array of type quux that's 32 elements big, it will span from the beginning of it's allocation, to the beginning of it's allocation plus 32*sizeof(quux), since each cell of the array is sizeof(quux) big. So, really when we specify an element of an array with array[n], that's just syntactic sugar (shorthand) for *(array+sizeof(quux)*n). Pointer arithmetic is really just changing the address that you're referring to, which is why we can implement strlen with
while(*n++ != '\0'){
len++;
}
since we're just scanning along, byte by byte until we hit a zero. Hope that helps!

There are several ways to tackle it.
The intuitive approach, which is what most C/C++ programmers think of, is that pointers are memory addresses. litb's example takes this approach. If you have a null pointer (which on most machines corresponds to the address 0), and you add the size of an int, you get the address 4. This implies that pointers are basically just fancy integers.
Unfortunately, there are a few problems with this. To begin with, it may not work.
A null pointer is not guaranteed to actually use the address 0. (Although assigning the constant 0 to a pointer yields the null pointer).
Further, you're not allowed to increment the null pointer, or more generally, a pointer must always point to allocated memory (or one element past), or the special null pointer constant 0.
So a more correct way of thinking of it is that pointers are simply iterators allowing you to iterate over allocated memory.
This is really one of the key ideas behind the STL iterators. They're modelled to behave very much as pointers, and to provide specializations that patch up raw pointers to work as proper iterators.
A more elaborate explanation of this is given here, for example.
But this latter view means that you should really explain STL iterators, and then simply say that pointers are a special case of these. You can increment a pointer to point to the next element in the buffer, just like you can a std::vector<int>::iterator. It can point one element past the end of an array, just like the end iterator in any other container. You can subtract two pointers that point into the same buffer to get the number of elements between them, just like you can with iterators, and just like with iterators, if the pointers point into separate buffers, you can not meaningfully compare them. (For a practical example of why not, consider what happens in a segmented memory space. What's the distance between two pointers pointing to separate segments?)
Of course in practice, there's a very close correlation between CPU addresses and C/C++ pointers. But they're not exactly the same thing. Pointers have a few limitations that may not be strictly necessary on your CPU.
Of course, most C++ programmers muddle by on the first understanding, even though it's technically incorrect. It's typically close enough to how your code ends up behaving that people think they get it, and move on.
But for someone coming from Java, and just learning about pointers from scratch, the latter explanation may be just as easily understood, and it's going to spring fewer surprises on them later.

This is one pretty good at link here about Pointer Arithmetic
For example:
Pointer and array
Formula for computing the address of ptr + i where ptr has type T *. then the formula for the address is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( T ) * i ]
For for type of int on 32bit platform, addr(ptr+i) = addr(ptr)+4*i;
Subtraction
We can also compute ptr - i. For example, suppose we have an int array called arr.
int arr[ 10 ] ;
int * p1, * p2 ;
p1 = arr + 3 ; // p1 == & arr[ 3 ]
p2 = p1 - 2 ; // p1 == & arr[ 1 ]

Related

What does it mean when strcmp has a plus sign? [duplicate]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Does anyone have any good articles or explanations (blogs, examples) for pointer arithmetic? Figure the audience is a bunch of Java programmers learning C and C++.
Here is where I learned pointers: http://www.cplusplus.com/doc/tutorial/pointers.html
Once you understand pointers, pointer arithmetic is easy. The only difference between it and regular arithmetic is that the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. For example, if you have a pointer to an int and an int's size is 4 bytes, (pointer_to_int + 4) will evaluate to a memory address 16 bytes (4 ints) ahead.
So when you write
(a_pointer + a_number)
in pointer arithmetic, what's really happening is
(a_pointer + (a_number * sizeof(*a_pointer)))
in regular arithmetic.
First, the binky video may help. It's a nice video about pointers. For arithmetic, here is an example:
int * pa = NULL;
int * pb = NULL;
pa += 1; // pa++. behind the scenes, add sizeof(int) bytes
assert((pa - pb) == 1);
print_out(pa); // possibly outputs 0x4
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(Note that incrementing a pointer that contains a null pointer value strictly is undefined behavior. We used NULL because we were only interested in the value of the pointer. Normally, only use increment/decrement when pointing to elements of an array).
The following shows two important concepts
addition/subtraction of a integer to a pointer means move the pointer forward / backward by N elements. So if an int is 4 bytes big, pa could contain 0x4 on our platform after having incremented by 1.
subtraction of a pointer by another pointer means getting their distance, measured by elements. So subtracting pb from pa will yield 1, since they have one element distance.
On a practical example. Suppose you write a function and people provide you with an start and end pointer (very common thing in C++):
void mutate_them(int *begin, int *end) {
// get the amount of elements
ptrdiff_t n = end - begin;
// allocate space for n elements to do something...
// then iterate. increment begin until it hits end
while(begin != end) {
// do something
begin++;
}
}
ptrdiff_t is what is the type of (end - begin). It may be a synonym for "int" for some compiler, but may be another type for another one. One cannot know, so one chooses the generic typedef ptrdiff_t.
applying NLP, call it address arithmetic. 'pointers' are feared and misunderstood mostly because they are taught by the wrong people and/or at the wrong stage with wrong examples in the wrong way. It is no wonder that nobody 'gets' it.
when teaching pointers, the faculty goes on about "p is a pointer to a, the value of p is the address of a" and so on. it just wont work. here is the raw material for you to build with. practice with it and your students will get it.
'int a', a is an integer, it stores integer type values.
'int* p', p is an 'int star', it stores 'int star' type values.
'a' is how you get the 'what' integer stored in a (try not to use 'value of a')
'&a' is how you get the 'where' a itself is stored (try to say 'address')
'b = a' for this to work, both sides must be of the same type. if a is int, b must be capable of storing an int. (so ______ b, the blank is filled with 'int')
'p = &a' for this to work, both sides must be of the same type. if a is an integer, &a is an address, p must be capable of storing addresses of integers. (so ______ p, the blank is filled with 'int *')
now write int *p differently to bring out the type information:
int* | p
what is 'p'? ans: it is 'int *'. so 'p' is an address of an integer.
int | *p
what is '*p'? ans: it is an 'int'. so '*p' is an integer.
now on to the address arithmetic:
int a;
a=1;
a=a+1;
what are we doing in 'a=a+1'? think of it as 'next'. Because a is a number, this is like saying 'next number'. Since a holds 1, saying 'next' will make it 2.
// fallacious example. you have been warned!!!
int *p
int a;
p = &a;
p=p+1;
what are we doing in 'p=p+1'? it is still saying 'next'. This time, p is not a number but an address. So what we are saying is 'next address'. Next address depends on the data type, more specifically on the size of the data type.
printf("%d %d %d", sizeof(char), sizeof(int), sizeof(float));
so 'next' for an address will move forward sizeof(data type).
this has worked for me and all of the people I used to teach.
I consider a good example of pointer arithmetic the following string length function:
int length(char *s)
{
char *str = s;
while(*str++);
return str - s;
}
So, the key thing to remember is that a pointer is just a word-sized variable that's typed for dereferencing. That means that whether it's a void *, int *, long long **, it's still just a word sized variable. The difference between these types is what the compiler considers the dereferenced type. Just to clarify, word sized means width of a virtual address. If you don't know what this means, just remember on a 64-bit machine, pointers are 8 bytes, and on a 32-bit machine, pointers are 4 bytes. The concept of an address is SUPER important in understanding pointers. An address is a number capable of uniquely identifying a certain location in memory. Everything in memory has an address. For our purposes, we can say that every variable has an address. This isn't necessarily always true, but the compiler lets us assume this. The address itself is byte granular, meaning 0x0000000 specifies the beginning of memory, and 0x00000001 is one byte into memory. This means that by adding one to a pointer, we're moving one byte forward into memory. Now, lets take arrays. If you create an array of type quux that's 32 elements big, it will span from the beginning of it's allocation, to the beginning of it's allocation plus 32*sizeof(quux), since each cell of the array is sizeof(quux) big. So, really when we specify an element of an array with array[n], that's just syntactic sugar (shorthand) for *(array+sizeof(quux)*n). Pointer arithmetic is really just changing the address that you're referring to, which is why we can implement strlen with
while(*n++ != '\0'){
len++;
}
since we're just scanning along, byte by byte until we hit a zero. Hope that helps!
There are several ways to tackle it.
The intuitive approach, which is what most C/C++ programmers think of, is that pointers are memory addresses. litb's example takes this approach. If you have a null pointer (which on most machines corresponds to the address 0), and you add the size of an int, you get the address 4. This implies that pointers are basically just fancy integers.
Unfortunately, there are a few problems with this. To begin with, it may not work.
A null pointer is not guaranteed to actually use the address 0. (Although assigning the constant 0 to a pointer yields the null pointer).
Further, you're not allowed to increment the null pointer, or more generally, a pointer must always point to allocated memory (or one element past), or the special null pointer constant 0.
So a more correct way of thinking of it is that pointers are simply iterators allowing you to iterate over allocated memory.
This is really one of the key ideas behind the STL iterators. They're modelled to behave very much as pointers, and to provide specializations that patch up raw pointers to work as proper iterators.
A more elaborate explanation of this is given here, for example.
But this latter view means that you should really explain STL iterators, and then simply say that pointers are a special case of these. You can increment a pointer to point to the next element in the buffer, just like you can a std::vector<int>::iterator. It can point one element past the end of an array, just like the end iterator in any other container. You can subtract two pointers that point into the same buffer to get the number of elements between them, just like you can with iterators, and just like with iterators, if the pointers point into separate buffers, you can not meaningfully compare them. (For a practical example of why not, consider what happens in a segmented memory space. What's the distance between two pointers pointing to separate segments?)
Of course in practice, there's a very close correlation between CPU addresses and C/C++ pointers. But they're not exactly the same thing. Pointers have a few limitations that may not be strictly necessary on your CPU.
Of course, most C++ programmers muddle by on the first understanding, even though it's technically incorrect. It's typically close enough to how your code ends up behaving that people think they get it, and move on.
But for someone coming from Java, and just learning about pointers from scratch, the latter explanation may be just as easily understood, and it's going to spring fewer surprises on them later.
This is one pretty good at link here about Pointer Arithmetic
For example:
Pointer and array
Formula for computing the address of ptr + i where ptr has type T *. then the formula for the address is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( T ) * i ]
For for type of int on 32bit platform, addr(ptr+i) = addr(ptr)+4*i;
Subtraction
We can also compute ptr - i. For example, suppose we have an int array called arr.
int arr[ 10 ] ;
int * p1, * p2 ;
p1 = arr + 3 ; // p1 == & arr[ 3 ]
p2 = p1 - 2 ; // p1 == & arr[ 1 ]

Need help understanding pointers in some sample code [duplicate]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Does anyone have any good articles or explanations (blogs, examples) for pointer arithmetic? Figure the audience is a bunch of Java programmers learning C and C++.
Here is where I learned pointers: http://www.cplusplus.com/doc/tutorial/pointers.html
Once you understand pointers, pointer arithmetic is easy. The only difference between it and regular arithmetic is that the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. For example, if you have a pointer to an int and an int's size is 4 bytes, (pointer_to_int + 4) will evaluate to a memory address 16 bytes (4 ints) ahead.
So when you write
(a_pointer + a_number)
in pointer arithmetic, what's really happening is
(a_pointer + (a_number * sizeof(*a_pointer)))
in regular arithmetic.
First, the binky video may help. It's a nice video about pointers. For arithmetic, here is an example:
int * pa = NULL;
int * pb = NULL;
pa += 1; // pa++. behind the scenes, add sizeof(int) bytes
assert((pa - pb) == 1);
print_out(pa); // possibly outputs 0x4
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(Note that incrementing a pointer that contains a null pointer value strictly is undefined behavior. We used NULL because we were only interested in the value of the pointer. Normally, only use increment/decrement when pointing to elements of an array).
The following shows two important concepts
addition/subtraction of a integer to a pointer means move the pointer forward / backward by N elements. So if an int is 4 bytes big, pa could contain 0x4 on our platform after having incremented by 1.
subtraction of a pointer by another pointer means getting their distance, measured by elements. So subtracting pb from pa will yield 1, since they have one element distance.
On a practical example. Suppose you write a function and people provide you with an start and end pointer (very common thing in C++):
void mutate_them(int *begin, int *end) {
// get the amount of elements
ptrdiff_t n = end - begin;
// allocate space for n elements to do something...
// then iterate. increment begin until it hits end
while(begin != end) {
// do something
begin++;
}
}
ptrdiff_t is what is the type of (end - begin). It may be a synonym for "int" for some compiler, but may be another type for another one. One cannot know, so one chooses the generic typedef ptrdiff_t.
applying NLP, call it address arithmetic. 'pointers' are feared and misunderstood mostly because they are taught by the wrong people and/or at the wrong stage with wrong examples in the wrong way. It is no wonder that nobody 'gets' it.
when teaching pointers, the faculty goes on about "p is a pointer to a, the value of p is the address of a" and so on. it just wont work. here is the raw material for you to build with. practice with it and your students will get it.
'int a', a is an integer, it stores integer type values.
'int* p', p is an 'int star', it stores 'int star' type values.
'a' is how you get the 'what' integer stored in a (try not to use 'value of a')
'&a' is how you get the 'where' a itself is stored (try to say 'address')
'b = a' for this to work, both sides must be of the same type. if a is int, b must be capable of storing an int. (so ______ b, the blank is filled with 'int')
'p = &a' for this to work, both sides must be of the same type. if a is an integer, &a is an address, p must be capable of storing addresses of integers. (so ______ p, the blank is filled with 'int *')
now write int *p differently to bring out the type information:
int* | p
what is 'p'? ans: it is 'int *'. so 'p' is an address of an integer.
int | *p
what is '*p'? ans: it is an 'int'. so '*p' is an integer.
now on to the address arithmetic:
int a;
a=1;
a=a+1;
what are we doing in 'a=a+1'? think of it as 'next'. Because a is a number, this is like saying 'next number'. Since a holds 1, saying 'next' will make it 2.
// fallacious example. you have been warned!!!
int *p
int a;
p = &a;
p=p+1;
what are we doing in 'p=p+1'? it is still saying 'next'. This time, p is not a number but an address. So what we are saying is 'next address'. Next address depends on the data type, more specifically on the size of the data type.
printf("%d %d %d", sizeof(char), sizeof(int), sizeof(float));
so 'next' for an address will move forward sizeof(data type).
this has worked for me and all of the people I used to teach.
I consider a good example of pointer arithmetic the following string length function:
int length(char *s)
{
char *str = s;
while(*str++);
return str - s;
}
So, the key thing to remember is that a pointer is just a word-sized variable that's typed for dereferencing. That means that whether it's a void *, int *, long long **, it's still just a word sized variable. The difference between these types is what the compiler considers the dereferenced type. Just to clarify, word sized means width of a virtual address. If you don't know what this means, just remember on a 64-bit machine, pointers are 8 bytes, and on a 32-bit machine, pointers are 4 bytes. The concept of an address is SUPER important in understanding pointers. An address is a number capable of uniquely identifying a certain location in memory. Everything in memory has an address. For our purposes, we can say that every variable has an address. This isn't necessarily always true, but the compiler lets us assume this. The address itself is byte granular, meaning 0x0000000 specifies the beginning of memory, and 0x00000001 is one byte into memory. This means that by adding one to a pointer, we're moving one byte forward into memory. Now, lets take arrays. If you create an array of type quux that's 32 elements big, it will span from the beginning of it's allocation, to the beginning of it's allocation plus 32*sizeof(quux), since each cell of the array is sizeof(quux) big. So, really when we specify an element of an array with array[n], that's just syntactic sugar (shorthand) for *(array+sizeof(quux)*n). Pointer arithmetic is really just changing the address that you're referring to, which is why we can implement strlen with
while(*n++ != '\0'){
len++;
}
since we're just scanning along, byte by byte until we hit a zero. Hope that helps!
There are several ways to tackle it.
The intuitive approach, which is what most C/C++ programmers think of, is that pointers are memory addresses. litb's example takes this approach. If you have a null pointer (which on most machines corresponds to the address 0), and you add the size of an int, you get the address 4. This implies that pointers are basically just fancy integers.
Unfortunately, there are a few problems with this. To begin with, it may not work.
A null pointer is not guaranteed to actually use the address 0. (Although assigning the constant 0 to a pointer yields the null pointer).
Further, you're not allowed to increment the null pointer, or more generally, a pointer must always point to allocated memory (or one element past), or the special null pointer constant 0.
So a more correct way of thinking of it is that pointers are simply iterators allowing you to iterate over allocated memory.
This is really one of the key ideas behind the STL iterators. They're modelled to behave very much as pointers, and to provide specializations that patch up raw pointers to work as proper iterators.
A more elaborate explanation of this is given here, for example.
But this latter view means that you should really explain STL iterators, and then simply say that pointers are a special case of these. You can increment a pointer to point to the next element in the buffer, just like you can a std::vector<int>::iterator. It can point one element past the end of an array, just like the end iterator in any other container. You can subtract two pointers that point into the same buffer to get the number of elements between them, just like you can with iterators, and just like with iterators, if the pointers point into separate buffers, you can not meaningfully compare them. (For a practical example of why not, consider what happens in a segmented memory space. What's the distance between two pointers pointing to separate segments?)
Of course in practice, there's a very close correlation between CPU addresses and C/C++ pointers. But they're not exactly the same thing. Pointers have a few limitations that may not be strictly necessary on your CPU.
Of course, most C++ programmers muddle by on the first understanding, even though it's technically incorrect. It's typically close enough to how your code ends up behaving that people think they get it, and move on.
But for someone coming from Java, and just learning about pointers from scratch, the latter explanation may be just as easily understood, and it's going to spring fewer surprises on them later.
This is one pretty good at link here about Pointer Arithmetic
For example:
Pointer and array
Formula for computing the address of ptr + i where ptr has type T *. then the formula for the address is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( T ) * i ]
For for type of int on 32bit platform, addr(ptr+i) = addr(ptr)+4*i;
Subtraction
We can also compute ptr - i. For example, suppose we have an int array called arr.
int arr[ 10 ] ;
int * p1, * p2 ;
p1 = arr + 3 ; // p1 == & arr[ 3 ]
p2 = p1 - 2 ; // p1 == & arr[ 1 ]

C arrays and pointers: equivalent pointer to array element

Edit: The similar question asked before has not addressed some perspectives related to the issue.
In the ANSI C book by Kernighan and Ritchie, they say that the following are equivalent
a[i]
*(a+i)
I don't see how this can be true for elements that occupy more than one address space, e.g. structs.
Please explain? Edit: Thank you for all answers, but I don't quite understand it. It would seem I am suffering the same confusion as #CucumisSativus from his answer and comments to it.
Say sizeof(*a) is 3. If for some reason I wanted to access the middle byte of the first element in a, I had thought this is how I would do it: *(a+1).
Say the address of a is 10, and the sizeof each element is 20. And say we want to get the pointer to the second element. As I see it, we could do this: p = (10 + 20). I thought this would be equivalent to &a[1].
I'm having real trouble explaining what I don't understand!!
Pointer arithmetic is treated differently than regular integer arithmetic in C. Adding an integer i to a pointer p advances the memory address by i * sizeof(*p), i.e., by i times the size of the type being pointed to.
As a potentially interesting, but practically useless, sidenote: due to the definition of p[i] as *(p+i), the expression i[p] is also equivalent to the same…
The + operator is not meant to be the next element in the address space.
The increment is defined by the size of the data type involved. Thus, a + 1 will refer to the next int if a is a pointer to an integer, and will refer to the next struct if a is a pointer to a struct.
Lets say we have an Integer pointer and a Character pointer as follows
int *a;
char *b;
Now assume that a is stored at location 10000
and b is stored at location 20000
So by doing the following operations
*(a+1) : It will return the value contained in address 10004 i.e. (10000+4)
*(b+1) : It will return the value contained in address 20001 i.e. (20000+1)
Reason:
Pointer addition is different from regular arithmetic addition. If you add 1 to an integer pointer it advances the pointer to a location by the size of the integer. So in this case it advances the pointer to 10004. Since character is only 1 byte long it advances the pointer by 1 byte.
a+i is translated to something like this in pseudo code
*(a+i*sizeof(variableType))
I read more of K&R and found the missing pieces to the puzzle, allowing me to rationalise what's happening. (Whether I'm correct or not is open to debate!)
From what I gather, the following is simply invalid:
p = (10 + 20)
Given that, to quote: "Pointers and integers are not interchangeable. Zero is the only exception."
I interpret this to mean that *(a+i) is not performing straight forward integer arithmetic.
I believe this behaviour is determined by the existence of a pointer in the expression.
And to quote K&R again, and other answers provided to my question, the exact behaviour of arithmetic of arithmetic involving:
one pointer with
one or more integers
for (p + n) is defined like so: "n is scaled according to the size of the objects p points to, which is determined by the declaration of p".
I realised what caused me to be so confused: I have in the past been able to use printf() to output the actual address value of a pointer. I believe this is "undefined behaviour" which the compiler I was using happened to handle by treating the pointer as an integer.
Similarly, given the above two numbered bullet points, and the definition that uses them, I gather that adding two pointers together (of the same type) results in undefined behaviour, and more certainly, adding two pointers of different types.
To get the nth byte of an integer, see this question.
K&R later adds that the following are legal pointer operations:
Assigning one pointer to another (of the same type)
Adding or subtracting a pointer and an integer
Subtracting one pointer from another (to the same array)
Comparing pointers (to the same array)
Assigning / comparing to 0
All other pointer arithmetic is illegal.

Explain variable declaration in C

I found this declaration in a C program
char huge * far *p;
Explanation: p is huge pointer, *p is far pointer and **p is char type
data variable.
Please explain declaration in more detail.
PS: I'm not asking about huge or far pointer here. I'm a newbie to programming
**p is character.Now a pointer pointing to address of this character will have value &(**p). Again if you want to take pointer to this pointer then next will be &(*p) and result will be p only.
If you read below sentence from right to left, you will get it all
p is huge pointer, *p is far pointer and **p is char type data variable.
In a nutshell virtual addresses on an Intel x86 chip have two components - a selector and an offset. The selector is an index into a table of base addresses [2] and the offset is added onto that base address. This was designed to let the processor access 20 bit (on a 8086/8, 186), 30 bit (286) or 46 bit (386 and later) virtual address spaces without needing registers that big.
'far' pointers have an explicit selector. However when you do pointer arithmetic on them the selector isn't modified.
'huge' pointers have an explicit selector. When you do pointer arithmetic on them though the selector can change.
Huge and far pointers are not part of standard C. They are borland extensions to the C language for managing segmented memory in DOS and Windows 16/32bit. Functionally, what the declaration says is **p is a char. That means "dereference p to get a pointer to char, dereference that to get a char"
In order to understand C pointer declarator semantics try this expression instead:
int* p;
It means p is a pointer to int. (hint: read from right to left)
int* const p;
This means p is a const pointer to int. (so you can't change the value of p)
Here's a proof of that:
p= 42; // error: assignment of read-only variable ‘p’
Another example:
int* const* lol;
This means lol is a pointer to const pointer to int. So the pointer which lol points at cannot point at another int.
lol= &p; // and yes, p cannot be reassigned, so we are correct.
In most cases reading from right to left makes sense. Now read the expression in question from right to left:
char huge * far *p;
Now the huge and far are just behaviour specifiers for pointers created by borland. What it actually means is
char** p;
"p is a pointer to pointer to char"
That means whatever p points to, points to a char.
Back in the 16-bit days on 8086, it would have declared a 32-bit pointer to a "normalized" 32-bit pointer to char (or to the first of an array thereof).
The difference exists because 32-bit pointers were composed of a segment number and offset between that segment, and segments overlapped (which meant two different pointers could point to the same physical address; example: 0x1200:1000 and 0x1300:0000). The huge qualifier forced a normalization using the highest segment number (and therefore, the lowest possible offset).
However, this normalization had a cost performance-wise, because after each operation that modified a pointer, the compiler had to automatically insert a code like this:
ptr = normalize(ptr);
with:
void huge * normalize(void huge *input)
{
unsigned long input2 = (unsigned long)input;
unsigned short segment = input >> 16;
unsigned short offset = (unsigned short)input;
segment += (offset >> 4);
offset &= 0x000F;
return ((unsigned long)segment) << 16 | offset;
}
The upside was the advantage of using your memory like it was flat, without worrying about segments and offsets.
Clarification to the other answers:
The far keyword is non-standard C, but it is not just an old obsolete extension from ancient PC days. Today, there are many modern 8 and 16 bit CPUs that uses "banked" memory to extend the amount of addressable memory beyond 65k. Typically they use a special register to pick a memory bank, effectively ending up with 24-bit addresses. All small microcontrollers on the market with RAM+flash memory > 64kb use such features.

Pointer Arithmetic [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
Does anyone have any good articles or explanations (blogs, examples) for pointer arithmetic? Figure the audience is a bunch of Java programmers learning C and C++.
Here is where I learned pointers: http://www.cplusplus.com/doc/tutorial/pointers.html
Once you understand pointers, pointer arithmetic is easy. The only difference between it and regular arithmetic is that the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. For example, if you have a pointer to an int and an int's size is 4 bytes, (pointer_to_int + 4) will evaluate to a memory address 16 bytes (4 ints) ahead.
So when you write
(a_pointer + a_number)
in pointer arithmetic, what's really happening is
(a_pointer + (a_number * sizeof(*a_pointer)))
in regular arithmetic.
First, the binky video may help. It's a nice video about pointers. For arithmetic, here is an example:
int * pa = NULL;
int * pb = NULL;
pa += 1; // pa++. behind the scenes, add sizeof(int) bytes
assert((pa - pb) == 1);
print_out(pa); // possibly outputs 0x4
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(Note that incrementing a pointer that contains a null pointer value strictly is undefined behavior. We used NULL because we were only interested in the value of the pointer. Normally, only use increment/decrement when pointing to elements of an array).
The following shows two important concepts
addition/subtraction of a integer to a pointer means move the pointer forward / backward by N elements. So if an int is 4 bytes big, pa could contain 0x4 on our platform after having incremented by 1.
subtraction of a pointer by another pointer means getting their distance, measured by elements. So subtracting pb from pa will yield 1, since they have one element distance.
On a practical example. Suppose you write a function and people provide you with an start and end pointer (very common thing in C++):
void mutate_them(int *begin, int *end) {
// get the amount of elements
ptrdiff_t n = end - begin;
// allocate space for n elements to do something...
// then iterate. increment begin until it hits end
while(begin != end) {
// do something
begin++;
}
}
ptrdiff_t is what is the type of (end - begin). It may be a synonym for "int" for some compiler, but may be another type for another one. One cannot know, so one chooses the generic typedef ptrdiff_t.
applying NLP, call it address arithmetic. 'pointers' are feared and misunderstood mostly because they are taught by the wrong people and/or at the wrong stage with wrong examples in the wrong way. It is no wonder that nobody 'gets' it.
when teaching pointers, the faculty goes on about "p is a pointer to a, the value of p is the address of a" and so on. it just wont work. here is the raw material for you to build with. practice with it and your students will get it.
'int a', a is an integer, it stores integer type values.
'int* p', p is an 'int star', it stores 'int star' type values.
'a' is how you get the 'what' integer stored in a (try not to use 'value of a')
'&a' is how you get the 'where' a itself is stored (try to say 'address')
'b = a' for this to work, both sides must be of the same type. if a is int, b must be capable of storing an int. (so ______ b, the blank is filled with 'int')
'p = &a' for this to work, both sides must be of the same type. if a is an integer, &a is an address, p must be capable of storing addresses of integers. (so ______ p, the blank is filled with 'int *')
now write int *p differently to bring out the type information:
int* | p
what is 'p'? ans: it is 'int *'. so 'p' is an address of an integer.
int | *p
what is '*p'? ans: it is an 'int'. so '*p' is an integer.
now on to the address arithmetic:
int a;
a=1;
a=a+1;
what are we doing in 'a=a+1'? think of it as 'next'. Because a is a number, this is like saying 'next number'. Since a holds 1, saying 'next' will make it 2.
// fallacious example. you have been warned!!!
int *p
int a;
p = &a;
p=p+1;
what are we doing in 'p=p+1'? it is still saying 'next'. This time, p is not a number but an address. So what we are saying is 'next address'. Next address depends on the data type, more specifically on the size of the data type.
printf("%d %d %d", sizeof(char), sizeof(int), sizeof(float));
so 'next' for an address will move forward sizeof(data type).
this has worked for me and all of the people I used to teach.
I consider a good example of pointer arithmetic the following string length function:
int length(char *s)
{
char *str = s;
while(*str++);
return str - s;
}
So, the key thing to remember is that a pointer is just a word-sized variable that's typed for dereferencing. That means that whether it's a void *, int *, long long **, it's still just a word sized variable. The difference between these types is what the compiler considers the dereferenced type. Just to clarify, word sized means width of a virtual address. If you don't know what this means, just remember on a 64-bit machine, pointers are 8 bytes, and on a 32-bit machine, pointers are 4 bytes. The concept of an address is SUPER important in understanding pointers. An address is a number capable of uniquely identifying a certain location in memory. Everything in memory has an address. For our purposes, we can say that every variable has an address. This isn't necessarily always true, but the compiler lets us assume this. The address itself is byte granular, meaning 0x0000000 specifies the beginning of memory, and 0x00000001 is one byte into memory. This means that by adding one to a pointer, we're moving one byte forward into memory. Now, lets take arrays. If you create an array of type quux that's 32 elements big, it will span from the beginning of it's allocation, to the beginning of it's allocation plus 32*sizeof(quux), since each cell of the array is sizeof(quux) big. So, really when we specify an element of an array with array[n], that's just syntactic sugar (shorthand) for *(array+sizeof(quux)*n). Pointer arithmetic is really just changing the address that you're referring to, which is why we can implement strlen with
while(*n++ != '\0'){
len++;
}
since we're just scanning along, byte by byte until we hit a zero. Hope that helps!
There are several ways to tackle it.
The intuitive approach, which is what most C/C++ programmers think of, is that pointers are memory addresses. litb's example takes this approach. If you have a null pointer (which on most machines corresponds to the address 0), and you add the size of an int, you get the address 4. This implies that pointers are basically just fancy integers.
Unfortunately, there are a few problems with this. To begin with, it may not work.
A null pointer is not guaranteed to actually use the address 0. (Although assigning the constant 0 to a pointer yields the null pointer).
Further, you're not allowed to increment the null pointer, or more generally, a pointer must always point to allocated memory (or one element past), or the special null pointer constant 0.
So a more correct way of thinking of it is that pointers are simply iterators allowing you to iterate over allocated memory.
This is really one of the key ideas behind the STL iterators. They're modelled to behave very much as pointers, and to provide specializations that patch up raw pointers to work as proper iterators.
A more elaborate explanation of this is given here, for example.
But this latter view means that you should really explain STL iterators, and then simply say that pointers are a special case of these. You can increment a pointer to point to the next element in the buffer, just like you can a std::vector<int>::iterator. It can point one element past the end of an array, just like the end iterator in any other container. You can subtract two pointers that point into the same buffer to get the number of elements between them, just like you can with iterators, and just like with iterators, if the pointers point into separate buffers, you can not meaningfully compare them. (For a practical example of why not, consider what happens in a segmented memory space. What's the distance between two pointers pointing to separate segments?)
Of course in practice, there's a very close correlation between CPU addresses and C/C++ pointers. But they're not exactly the same thing. Pointers have a few limitations that may not be strictly necessary on your CPU.
Of course, most C++ programmers muddle by on the first understanding, even though it's technically incorrect. It's typically close enough to how your code ends up behaving that people think they get it, and move on.
But for someone coming from Java, and just learning about pointers from scratch, the latter explanation may be just as easily understood, and it's going to spring fewer surprises on them later.
This is one pretty good at link here about Pointer Arithmetic
For example:
Pointer and array
Formula for computing the address of ptr + i where ptr has type T *. then the formula for the address is:
addr( ptr + i ) = addr( ptr ) + [ sizeof( T ) * i ]
For for type of int on 32bit platform, addr(ptr+i) = addr(ptr)+4*i;
Subtraction
We can also compute ptr - i. For example, suppose we have an int array called arr.
int arr[ 10 ] ;
int * p1, * p2 ;
p1 = arr + 3 ; // p1 == & arr[ 3 ]
p2 = p1 - 2 ; // p1 == & arr[ 1 ]

Resources