C programming: working with pointers

In summary, when you subtract two pointers, you are telling the compiler how many houses are between the two addresses.
  • #1
Math Is Hard
Staff Emeritus
Science Advisor
Gold Member
4,652
37
I have run into a little bit of confusion working with pointers and I am trying to figure out which of the expressions below from my assignment are valid. My definition of a pointer is that it is a variable that contains a memory address, so I get confused about whether I am modifying a location or the value stored at the location. :confused: Could someone please look at my responses to the assignment below and straighten me out? Thanks!

Given that pi and pj are pointers to int, and ii and ij are ints, which of the following expressions are valid?

a) pi + ii I think this is valid. But I am not sure if the address that pi points to is getting the int added to it or the value at the address.
b) pi + pj I think this might be invalid. I don't think you can add a pointer to a pointer.
c) pi++ I think this is valid. pi points to a machine address, if pi isincremented by one, pi will point to one unit past that machine address.
 
Physics news on Phys.org
  • #2
a) is valid. You're essentially incrementing the pointer by ii memory spaces. If it pointed at location 0x100 before, and ii were 0x10, it now points at location 0x110.

b) is not valid, as you suspect. The resulting pointer might well lie outside the memory space of the computer.

c) is valid for the same reason as a. Keep in mind that pi++ is literally just a syntactic shortcut for pi = pi + 1, and is equivalent to it in every way.

- Warren
 
  • #3
Thanks, Warren. I guess I need to create some little programs and practice working with pointers to understand them better.
 
  • #4
First off, do you understand this?

Code:
int *pInteger, someVariable;
pInteger = &someVariable;
*pInteger=32;

The above indirectly relates to your questions because you have to truly understand what a pointer is and does.

I'm going to move on, but if you don't understand the above say so and all will be explained.

You are correct in saying that a pointer is a variable but sying that alone means that you understand what a variable is--which most people have a misconception here. A variable is not simply a container for data but rather a container for a specific type of data which by definition occupies a set amount of memory depending on the type of data. I know what I said was wordy so I'll simplify if I can. Most people have multiple cups in their cupboards. Measuring cups, coffee cups, drinking glasses, wine glasses, etc. Each cup was designed for a different purpose and to hold a different amount of liquid. Most coffee cups hold about the same amount of liquid(there are a few general sizes though small, mediau, large, and coffee addict size). Most measuring cups measure the same volume of liquid as do most wine glasses. What I'm getting at is that each cup holds a certain amount of data which is dictated by its intended use. When you ask for a cup of coffee you know what to expect. When you go to McDonalds, or Wendys you know to expect a 24oz medium(or something like that).

Variables in c are like cups because the compiler knows how much memory each data type occupies.

a) You are correct. When you add an integer to a pointer (not a pointer reference mind you) then the compiler knows to jump to the next block of memory, and not the next memory location.

example (using above code}:

lets say someVariambe resides at memory location 32000 (decimal)

if we say

pInteger+1;

the compiler doesn't assign 32001 to pInteger rather the compiler assigns 32004 because integers occupy 32 bits (4 bytes).

To recap, you are correct in thinking that adding an integer to a pointer is a valid operation.

b) Again here you are correct. adding a pointer to a pointer yields no valid useful information. If we look to the above where pInteger is stored at 32000. If we said pInteger+=pInteger then pIntegre "would" equal 64000. What's stored at 64000? Who knows. That's why pointer + pointer is invalid because it would simply move the location of the pointer to some memory location.

Here's the crazy bit---You can subtract pointers! That's right subtraction is legal and provides important information when working with arrays. If you point to two elements within an array using two seperat pointers. Subtracting one pointer from another tells you how far apart the elements are from each other within the array.

It works like this: if a row of houses where sitting on 75 foot wide lots and each lot was numbered sequentially then knowing any two addresses on the street would allow you to find the distance between those houses and the number of houses between the houses.

c) You are correct because pInteger++ is the concise form of pIntegre = pInteger +1. We've already said that adding integers to pointers is valid thus so is this.

Well, hope this helped, good luck.

[edit] I see that while I was entering my long explanation that you were blessed with another more concise response.
 
Last edited:
  • #5
faust9 brings a point I didn't wish to bring up, but it is important: when you work with pointers, adding 1 to them actually adds 1 * the size of the type of the pointer. As faust9 says, when you're working with int pointers (ints are 4 bytes long), adding 1 actually moves the pointer 4 bytes.

If you wanted to suppress this compiler convenience, you could cast your array to a void*. Adding one to a void pointer actually just adds one to the memory address. Normally the convenience is... convenient, however.

- Warren
 
  • #6
Yes, I actually was just replying to that comment faust9 made regarding that 4-byte increment for integers. My book doesn't illustrate this point well. That was very helpful, faust9. Thank you.
 
  • #7
faust9 said:
First off, do you understand this?

Code:
int *pInteger, someVariable;
pInteger = &someVariable;
*pInteger=32;
well... you tell me. This is how I interpret the lines:

first line: declares pInteger, a pointer to an int variable. Also declares an int variable called someVariable
second line: assigns the memory address of someVariable to pInteger
third line: changes the value at the address held by pInteger to 32 (so someVariable will now have the value 32)

faust9 said:
Variables in c are like cups because the compiler knows how much memory each data type occupies.

yes, I'm pretty clear on variables and data types.

faust9 said:
Here's the crazy bit---You can subtract pointers! That's right subtraction is legal and provides important information when working with arrays. If you point to two elements within an array using two seperat pointers. Subtracting one pointer from another tells you how far apart the elements are from each other within the array.

It works like this: if a row of houses where sitting on 75 foot wide lots and each lot was numbered sequentially then knowing any two addresses on the street would allow you to find the distance between those houses and the number of houses between the houses.

Then, referecing my previous examples, would this be a valid expression:

pi - pj

??
because I had assumed not before reading your post above!

faust9 said:
Well, hope this helped, good luck.

yes. Very much. Thank you. :smile:
 
  • #8
Math Is Hard said:
well... you tell me. This is how I interpret the lines:

first line: declares pInteger, a pointer to an int variable. Also declares an int variable called someVariable
second line: assigns the memory address of someVariable to pInteger
third line: changes the value at the address held by pInteger to 32 (so someVariable will now have the value 32)

Yep that's what's going on. I's not that tough once you get the hang of it but many people (I was just helping someone last night with this) get lost with * and &.

Then, referecing my previous examples, would this be a valid expression:

pi - pj

??
because I had assumed not before reading your post above!

Yep, subtraction is valid. Using pointer subtraction is fairly important when working with arrays especially when sorting the data stored within an array. Subtraction of pointers (when they point to elements within the same array) is used as a means of indexing elements of the array.
 
  • #9
This makes things much clearer. Just one small point I am confused on, and I think it's the term "valid".
If I add two pointers together I will get information that I can't use for indexing, that's quite clear, but is it truly "invalid"? When I hear "invalid", it sounds like if I attempt such an operation I'll get hit with an error message or my compiler will holler at me or something...
thanks
 
  • #10
It is physically possible, since pointers are just numbers, and you can add any two numbers you like. Your compiler may emit a warning or even an error, however, depending on how it is configured.

- Warren
 
  • #11
Thanks, chroot. I am curious to see what will happen if I try it now.
 
  • #12
I can't recall if pointer addition is specifically disallowed in the standard, but it seems to ring a bell as being so. Pointer addition could lead to some serious problems if allowed. Anywho, I use GCC 3 and I get an error "invalid operands to binary +" when I compiled the below program.

Code:
#include <stdio.h>

int main (int argc, const char * argv[]) 
{
	//the following is a test of the validity of adding pointers.
	int *pInteger, someVariable;
	pInteger = &someVariable;
	
	printf("Stored in pInteger: %d", pInteger);
	
	pInteger+=pInteger; //is this "valid"?
	
	printf("\nStored in pInteger += pInteger: %d", pInteger);
	return 0;
}

I think its safe to say the it is invalid.
 
Last edited:
  • #13
ints are 4 bytes long

I would just like to point out that this is also a compiler dependancy, although it will be true on most modern desktops. Don't be surprised when things don't work out when you're programming a Cray! :smile:


Adding one to a void pointer actually just adds one to the memory address.

I think this is also a compiler dependancy; I'm pretty sure I've had at least one compiler refuse to let me add to a void pointer.



Anyways, I'm pretty sure it is a requirement that the char type be exactly one byte, so you can use that if you like.
 
  • #14
I tried to do the pointer addition and my compiler also balked. In fact it very specifically said that pointer addition wasn't allowed (I use Visual C++).

I also experimented a little with pointer subtraction:

#include <stdio.h>
int main (void)
{
int *pInteger,*pInteger2, someVariable, someVariable2, diff;

pInteger = &someVariable;
pInteger2 = &someVariable2;

diff= pInteger-pInteger2; //try to subtract

printf("Stored in pInteger: %d \n", pInteger);
printf("Stored in pInteger2: %d \n", pInteger2);
printf("The difference is %d \n",diff);
return 0;
}
I was suprised to get this result:

Stored in pInteger: 1245044
Stored in pInteger2: 1245040
The difference is 1


only because I thought that pInteger would have the value 1245040
and pInteger2 would have the value 1245044
 
Last edited:
  • #15
p.s. I am looking for a tutor to help me through my last few chapters of this course. I am getting really bogged down and frustrated by some of this stuff and it's taking me hours and hours to finish the assignments. I am doing an online course so I don't have a lot of interaction with my teacher and I think I frequently misinterpret the book. If anyone is interested or knows a good C tutor, please PM me. thx.
 
  • #16
Well, many of us here are excellent tutors... Perhaps you should just post your difficulties on here? Rather than just one tutor, you'll have several.

- Warren
 
  • #17
I agree, chroot - you folks are THE BEST! I am so grateful for all the help I have gotten.
But I think I feel guilty about "over-posting" because I have so,so many questions. I just didn't want to become a nuisance.
 
  • #18
Don't feel guilty at all -- that's what this forum is all about!

If we didn't enjoy replying, we wouldn't. :smile:

- Warren
 
  • #19
thanks!
ok, then, many dumb questions coming later... (don't say I didn't warn you) :biggrin:
 
  • #20
another assignment

I am just going to post this one back in the same thread since we're talking about arrays and pointers. I would like someone to check my work. I am not sure I implemented the instructions correctly where it asks me to use array notation and then pointer notation. Thanks for your help.

assignment: Write a program that initializes an array of double
and then copies the contents of the array into two other arrays.
(All three arrays should be declared in the main program.)
To make the first copy, use a function with array notation.
To make the second copy, use a function with pointer notation and
pointer incrementing. Have each function take as arguments, the name
of the target array, and the number of elements to be copied, that is,
the function calls would look like this given the following declarations:

double source[5] = {1.1,2.2,3.3,4.4,5.5};
double target1[5];
double target2[5];
copy_arr(source,target1,5);
copy_ptr(source, target2,5);
 
Last edited:
  • #21
# include <stdio.h>
void copy_arr(double *ar1,double *ar2,int n); //prototype
void copy_ptr(double *ar1,double *ar2,int n); //prototype
int main(void)
{
double source[5] = {1.1,2.2,3.3,4.4,5.5};
double target1[5];
double target2[5];
int i;

copy_arr(source,target1,5); //call the array notation copy function

//test display of target1 array after copying values
for(i=0;i<5;i++)
printf("element %d of target1 contains %2.1f \n",i,target1);


copy_ptr(source, target2,5); //call pointer notation copy function

//test display of target2 array after copying values
for(i=0;i<5;i++)
printf("element %d of target2 contains %2.1f \n",i,target1);


return 0;

}

void copy_arr(double *ar1,double *ar2,int n)
{
int i;
for(i=0;i<n;i++)
ar2 = ar1;

}

void copy_ptr(double *ar1,double *ar2,int n)
{
int i;
for(i=0;i<n;i++)
ar2 = *(ar1 + i);

}
 
  • #22
I am still working on that formatting. I am not sure why indenting gives me the double-spacing. :redface:
 
  • #23
Indenting will also put a blank line between what you indent and the rest, and you can't go around this. What you should be doing is placing your code in [ code ] [ / code ] tags or even better [ php ] [ / php ] tags. Those php tags will do the same as code tags, with the added benefits of colouring things like data types, comments, etc. It knows what's a comment, and colours it orange. Here's an example:

This is the code without any tags around it. Note that I've put spaces and indentation manually, but it won't show up:

int main (void) {
int x, y = 7;
x = 5;
for (int i = 0; i < x; i++) {
y += i; // this does some stuff
}
return 0; // this does other stuff
}

Now, using [ code ] tags:

Code:
int main (void) {
    int x, y = 7;
    x = 5;
    for (int i = 0; i < x; i++) {
        y += i; // this does some stuff
    }
    return 0; // this does other stuff
}

(Of course, you won't have the spaces when you write "[ code ]"). Now, with the [ php ] tags:

PHP:
int main (void) {
    int x, y = 7;
    x = 5;
    for (int i = 0; i < x; i++) {
        y += i; // this does some stuff
    }
    return 0; // this does other stuff
}
 
  • #24
1) Just use the [ code ] tags for formatting. They preserve indentation.

2) Your copy_arr looks good. Your copy_ptr doesn't. You're using pointer notation on the right hand side of the assignment, but not on the left. Each time you go through the while loop, just increment both pointers.

- Warren
 
  • #25
SWEET! Thanks, AKG!
:biggrin: :biggrin: :biggrin:
 
  • #26
The last line of your last function:

ar2 = *(ar1 + i);

I would think you could make it:

*(ar2 + i) = *(ar1 + i);

Try it, because if it works, it seems more like what the assignment is asking.
 
  • #27
Thanks, Warren. :smile: I thought something was wrong. I'll try again and repost.
 
  • #28
PHP:
# include <stdio.h>
void copy_arr(double *ar1,double *ar2,int n); //prototype
void copy_ptr(double *ar1,double *ar2,int n); //prototype
int main(void)
{
     double source[5] = {1.1,2.2,3.3,4.4,5.5};
     double target1[5];
     double target2[5];
     int i;

     copy_arr(source,target1,5); //call the array notation copy function 

     //test display of target1 array after copying values
     for(i=0;i<5;i++)
          printf("element %d of target1 contains %2.1f \n",i,target1[i]);

     copy_ptr(source, target2,5); //call pointer notation copy function

     //test display of target2 array after copying values
     for(i=0;i<5;i++)
          printf("element %d of target2 contains %2.1f \n",i,target1[i]);

     return 0;
}

void copy_arr(double *ar1,double *ar2,int n)
{
     int i;
     for(i=0;i<n;i++)
          ar2[i] = ar1[i];
}

void copy_ptr(double *ar1,double *ar2,int n)
{
     int i;
     for(i=0;i<n;i++)
          *(ar2 + i) = *(ar1 + i);
}
 
Last edited:
  • #29
Yay! The function works great! And the PHP tags are the shiz-nit!

Thanks so much!
 
  • #30
Remember, with the php and code tags, you can indent manually. Look at my post. All three things were written the same. The stuff in normal text was written with spaces in front of the appropriate lines, they just don't show up. Put those in code or php tags and the spaces show up.
 
  • #31
Math Is Hard,

The assignment seemed to specifically ask for pointer incrementing, like this:

PHP:
void copy_ptr(double *ar1,double *ar2,int n)
{
   int i;
   for(i=0;i<n;i++)
      *(ar2++) = *(ar1++);
}
 
  • #32
php tags

I am SO loving this! Yeah - I just went back and indented and it was so EASY!
 
  • #33
chroot said:
Math Is Hard,

The assignment seemed to specifically ask for pointer incrementing, like this:

PHP:
void copy_ptr(double *ar1,double *ar2,int n)
{
   int i;
   for(i=0;i<n;i++)
      *(ar2++) = *(ar1++);
}

oops! sorry- I think I got carried away with the formatting fun stuff! :redface: so, I should use ++ for "pointer incrementing"?
using + i won't move to the correct position in the array?
 
  • #34
Math Is Hard,

Remember the three qualities of a good programmer:

1) Laziness. No one should have to do much work, so a good programmer should strive to make the user's life utterly push-button easy.

2) Impatience. No one should ever have to wait for a computer to do anything, so programmers should be careful with their algorithm designs to make sure their users never have to wait for anything.

3) Hubris. Programmers should take excessive pride in their work, and should strive to make every program they write complete, totally functional, and elegant.

The PHP tags are really an example of some programmer on the vBulletin team demonstrating quality number one.

- Warren
 
  • #35
Math Is Hard said:
oops! sorry- I think I got carried away with the formatting fun stuff! :redface: so, I should use ++ for "pointer incrementing"?
using + i won't move to the correct position in the array?
Your code using pointer arithmetic (the + signs) will certainly work, but it might not be the best way to meet the specification. The specification said to use pointer incrementing. Normally, I associate the ++ operator with the word "incrementing," but it may just be a semantic issue.

- Warren
 

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
17
Views
1K
  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
7
Views
3K
  • Introductory Physics Homework Help
Replies
4
Views
883
  • Programming and Computer Science
Replies
5
Views
872
  • Engineering and Comp Sci Homework Help
Replies
3
Views
661
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
19
Views
2K
  • Programming and Computer Science
Replies
5
Views
806
Back
Top