6.8 — Pointers, arrays, and pointer arithmetic

Pointers and arrays
Pointers and arrays are intricately linked in the C language. In previous lessons, you learned how to declare an array of variables:

anArray is actually a pointer that points to the first element of the array! Because the array variable is a pointer, you can dereference it, which returns array element 0:

Pointer arithmetic

The C language allows you to perform integer addition or subtraction operations on pointers. If pnPtr points to an integer, pnPtr + 1 is the address of the next integer in memory after pnPtr. pnPtr - 1 is the address of the previous integer before pnPtr.

Note that pnPtr+1 does not return the address after pnPtr, but the next object of the type that pnPtr points to. If pnPtr points to an integer (assuming 4 bytes), pnPtr+3 means 3 integers after pnPtr, which is 12 addresses after pnPtr. If pnPtr points to a char, which is always 1 byte, pnPtr+3 means 3 chars after pnPtr, which is 3 addresses after pnPtr.

When calculating the result of a pointer arithmetic expression, the compiler always multiplies the integer operand by the size of the object being pointed to. This is called scaling.

The following program:



As you can see, each of these addresses differs by 4 (7C + 4 = 80 in hexadecimal). This is because an integer is 4 bytes on the author’s machine.

The same program using short instead of int:



Because a short is 2 bytes, each address differs by 2.

It is rare to see the + and - operator used in such a manner with pointers. However, it is more common to see the ++ or -- operator being used to increment or decrement a pointer to point to the next or previous element in an array.

Pointer arithmetic and arrays

If anArray is a pointer that points to the first element (element 0) of the array, and adding 1 to a pointer already returns the next object, then anArray+1 must point to the second element (element 1) of the array! We can verify experimentally that this is true:

The parentheses are necessary to ensure the operator precedence is correct -- operator * has higher precedence than operator +.

Note that *(anArray+1) has the same effect as anArray[1]. It turns out that the array indexing operator ([]) actually does an implicit pointer addition and dereference! It just looks prettier.

We can use a pointer and pointer arithmetic to loop through an array. Although not commonly done this way (using indices is generally easier to read and less error prone), the following example goes to show it is possible:

This program uses a pointer to step through each of the elements in an array. Each element is dereferenced by the switch expression, and if the element is a vowel, nVowels is incremented. The for loop then uses the ++ operator to advance the pointer to the next character in the array. The for loop terminates when all characters have been examined.

The above program produces the result:

Mollie has 3 vowels
6.9 -- Dynamic memory allocation with new and delete
6.7 -- Introduction to pointers

48 comments to 6.8 — Pointers, arrays, and pointer arithmetic

  • Jacob

    Hi Alex!

    I’ve been learning C from your tutorial - and I think it’s really great, so thanks.
    However I just wanted to point (speaking of pointers ;-)) out, that the guy behind these two articles
    would have to disagree with you on whether arrays and pointers are the same. Personally, I don’t care if he is right, since the code presented here still works intentionally.

    Best regards

  • The author of those articles is right on some points and wrong on others. However, I find his logic and examples to be quite misleading. Rather than refute his arguments, instead, let me see if I can shed some light on the situation as I understand it.

    Arrays and pointers are not strictly identical. Although arrays are implemented using pointers, arrays also contain slightly more information. When you create an array, the compiler has to keep track of how many elements the array has. Otherwise, the compiler would not know how many elements to delete when it came time to delete[] the array.

    With a non-dynamically allocated array, it’s possible to see the actual size of the array:

    int anArray[5]; cout < < sizeof(anArray);

    This program prints out 20 (assuming 4-byte integers). This is the size of the array.

    On the other hand:

    int *ptr = anArray; cout < < sizeof(ptr);

    prints 4. This is the size of the pointer.

    When you access an array through a pointer, you're accessing it in a slightly limited manner, because you lose access to the size and type information of the original array. This can be a pain (because it means you have to store the size of the array in a separate variable) but that's about the extent of the practical consequences.

    Note that for dynamically allocated arrays:

    int *pnArray = new int[5]

    the new operator returns a pointer to the array, and that's all you ever have to work with. You never get access to the actual array object.

    Functionally, in terms of how you access an array, there is no real difference between accessing the elements of an actual array and accessing the elements of an array through a pointer.

    So technically, it is correct that arrays and pointers aren't identical. Pointers give you access to a limited subset of the array information. Practically speaking, it's generally not even worth worrying about.

  • Alex,

    Your site is wonderful, thanks for providing it. I was editing some of the examples you provide to see what happens with the output and I noticed something I cannot explain. When I substitute the following into your last example (Mollie/Vowels) I get the output 3, which makes sense.

    But When I change the code to the below, the result becomes 4, which I do not understand. It is as if the program is counting the last whitespace character as a vowel. Can you explain this to me?

    BTW, I am using Cygwin with Dev-C++ and the GNU compilers.

    Thanks and best regards,

    • When I ran your Lazy Brown Fox example with Visual C++ 2005, I got 3 vowels, not 4. So at the moment I’m not sure why you’re getting a different result.

      My advise to you would be to run your program using a debugger, and step through the code. Put a watch on nVowels and then watch it count up -- when it becomes 4, you’ll at least know what’s causing it.

  • Stuart

    This is going over my head:

    Could you explain it, please?

    • miroslav

      I’m sorry but would it be possible to explain? For example the ‘pnPtr <= szName + nArraySize)’

      • Hmmm, not sure how I missed the original comment here. Sure, here’s the explanation.

        In this example, szName is an array. As you have learned, arrays and pointers are intricately linked in C++. Let’s break this for loop into it’s 3 components and examine each one:

        This is creating a new pointer named pnPtr and setting it to point to the first character in the name array. After this, pnPtr and szName will be holding the same address.

        The tricky part of this is determining what szName + nArraySize means. Arrays are laid out contiguously in memory. If szName is the start of the array, and nArraySize is the length of the array, then szName + nArraySize must be the end of the array. So what this is really saying is, “while pnPtr hasn’t reached the end of the array, keep looping”.

        Increment the pnPtr pointer to the next character.

        So, putting it all together: “pnPtr is set to the start of the array. While it hasn’t reach the end of the array, do the loop, and then increment pnPtr to the next character”.

        That’s it.

        • Cory

          For the last part, “Increment the pnPtr pointer to the next character.”, did you mean increment the point to the address of the next character?

          • Moogie

            For what it’s worth (maybe more for others who read this, not necessarily Cory, who probably stopped caring about a response to this message months ago :)) I think the answer is: yes. Although, it’ll really be looking at the character at that address, as Alex said, not the address itself. But yes, you’re thinking along the right lines there.

  • Stuart

    It’s okay - I’ve come back to it with a clear head and I get it now. (And I realize that nArraySize-2 works.) :)

    Thanks for tutorials, BTW.

  • I am thankfull for above Information.I am doing C++ programming…and am doing a Project In Multiple Arrays, using Functions.

    Hope To Get More Information in this web.

    Thank you very much

    Savenaca yauyau

  • Nickell

    how would you sort an char array using pointers like you did above?

  • Alan Hurley

    “It turns out the the array” should read, “It turns out that the array”.

    [ Indeed! Thank you. -Alex ]

  • runner

    You’re making a one-off error here, I think:

    The for loop should run for


    since the junk data after szString[nArraySize - 1] might end up being a vowel (right?)

    [ You are correct. I changed the example so it loops the correct number of times. It still goes through the loop once when pnPtr is pointing to the terminating NULL, but this doesn’t hurt anything. -Alex ]

  • Noha

    I just wonder why did write in the last example (in for loop):
    char *pnPtr = szName
    in place of:
    char *pnPtr = *szName
    since you need the pointer of the first element in the array not the element itself!

  • Yogesh Shastri

    Great Site. A lot of things are said about sharing learning and wisdom, but a few are able to do it. You are one of them, and since you have done it with excellence, so kudos to you! I have tried to write tutorials for another programming language that I have learnt, but couldn’t do it, because of so many factors - so I can really appreciate your efforts. Thanks to you!

  • Yogesh Shastri

    Dear Alex,

    Thank you for providing this wonderful resource for learning C++. I was trying my luck at pointers, but when I wrote a code like this:

    void main()
    int arr[5]={1,2,3,4,5};
    char name[]=”Pratyush”;
    cout<< *arr++ <<endl;
    cout<< *name++ <<endl;

    I get error on line on which I use *arr++ and *name++ saying that an Lvalue is required. Could you please explain.

    Regards and bets wishes.

    • Sandesh


      L-Value means a quantity on left side of any equation or assignment.L-Values are always variables while values on right side(R-Values) are numbers or characters.The ++ operator requires varibles that is L-Values.

      The dereferencing operator “*” has higher precedency than the increment by 1 “++” operator.If the program would have exceuted,while excecuting the first cout, the operation *arr would be excecuted first then ++.*arr would result the address of first element of array ‘arr’ as array name is a pointer that addresses the first element.the address would be a hexadecimal number and therefore not a variable and ++ statement would not execute.Therefore,it shows L-value(variable) required.

      it is the same with second cout.* operator would now be the value of first element and therefore ++ would not execute.

      i hope you understood it.


      • rawr

        You say that *arr results in a hexadecimal number, yet when I type *arr it uses the value. Also, the code works with (*arr)++.

        Is this because addresses are simply treated differently to pointers by the compiler?

      • AUASP

        “the dereferencing operator “*” has higher precedency than the increment by 1 “++” operator”
        Actually the reverse is true.check any c++ associativity and precedence list.

  • Jacob Quadro

    Thanks for the great tutorial Alex.

    In the above code:
    const int nArraySize = 7;
    char szName[nArraySize] = “Mollie”;

    I’m confused why should nArraySize = 7, when Mollie is just six characters.
    I tried replacing it with 6 but it won’t compile.

    Thanks again.

    • Quinn

      You had forgotten to include the null terminating character, . Every C-string must end with the null terminating character, and as a direct result, all C-strings are sized to one larger than the string you’re putting into it. In essence, it would work out like this…

      Alex covered this in much more detail in C-Style Strings, so I’d suggest revisiting that section to see it in action.

      When you change nArraySize to equal 6, that meant that the szName array could only contain a string of five characters (because it MUST end with a null-terminating character, if it doesn’t, it causes overflows). So the compiler realizing this, issued a build error since this would inevitably, without fail, lead to an overflow. This is just one of the many little quirks of the C/C++ language, and computer programming in general, you’ll have to get used to. :)

  • kanks

    Actually, there is one place difference could matter

    a main function in file2.cpp calling “foo” will crash

  • Realth

    Why does cout << *(&szName) output the entire string ? Shouldn’t it only return the first character of szName ? &szName returns the address of the first element right ? So derefrencing it should give the first character.

    Also why does my compiler complain when I try this :

    I want pnPntr to point to the first Address of szName.

    Yet this works,

    Depending on what is on the left of szName, szName means completely different things!

    I get mollie..

    put a pointer declaration and suddenly szname is and address!

    It’s and address again! ??

    Is this just how it is ?

    Excellent tutorials by the way!

    • eric

      *(&szName) is doing inverse operations, so it ends up just szName. The value of szName is actually an address (because it’s a pointer to the first address in the array), but the compilers treat it differently because it’s a string. The compiler jumps to the address in szName and reads the values starting from that address until it hits a null.
      This is probably done for convenience, because when you’re looking at an array you usually want to see its contents and not its address. To access the first element, use *szName or szName[0]

      After playing with it for awhile, I found that this will work setting to the address of the szName. I have no idea why, however. Intuitively, this should set pnPntr to the address of the first element in the array which szName points to, but the value of (int*)szName matches &szName:

      However, changing the contents via “*pnPntr = “doesn’t work too well, as you’re limited to the first 4 characters’ ASCII values (my compiler had the added annoyance of outputting these in decimal rather than hex).

      Hopefully someone else can be a little more clear on all this, because I don’t know enough about it to say, yet.

  • Wow. I finally understand pointers! Yay!

    That is a pretty hand way of stepping through an array.

  • Andreas

    I really appreciate your guide! THANKS

  • This contains misinformation: “anArray is actually a pointer that points to the first element of the array”.

    An array is not a pointer, ever. An array is an array, a pointer is a pointer. This isn’t up for discussion, read the language standard. An array has an implicit array-to-pointer conversion, but that doesn’t make it a pointer anymore than it makes a function a pointer because a function-to-pointer conversion exists.

    The type of



    There are no pointers there.

    • Chris

      First, thanks so much for your work on this…your tutorial is a huge help, Alex!

      Walking through this portion on the use of pointers with arrays, I’m slightly confused by why using the reference operator (&) on a pointer created for a char array won’t return the value’s address, while one created for an int array will.

      For example the following code:

      Will output the following:

      pnPtr: Christopher *pnPtr: C
      pnPtr: hristopher *pnPtr: h
      pnPtr: ristopher *pnPtr: r
      pnPtr: istopher *pnPtr: i
      pnPtr: stopher *pnPtr: s
      pnPtr: topher *pnPtr: t
      pnPtr: opher *pnPtr: o
      pnPtr: pher *pnPtr: p
      pnPtr: her *pnPtr: h
      pnPtr: er *pnPtr: e
      pnPtr: r *pnPtr: r
      pnPtr: *pnPtr:
      Christopher has 3 vowels.

      …rather than a hex address for pnPtr.

      While setting up a random integer array and carrying out the same process (sans vowel counting)…

      …generates this output, with address output for the value of pnPtr and specific array entries for *pnPtr. (I expected the char array output to similar to this.)

      pnPtr: 0xbfc6e1d8 *pnPtr: 1
      pnPtr: 0xbfc6e1dc *pnPtr: 2
      pnPtr: 0xbfc6e1e0 *pnPtr: 3
      pnPtr: 0xbfc6e1e4 *pnPtr: 4
      pnPtr: 0xbfc6e1e8 *pnPtr: 5
      pnPtr: 0xbfc6e1ec *pnPtr: 10
      pnPtr: 0xbfc6e1f0 *pnPtr: 20

      Can you explain why C++ deals with them differently or what I’m doing improperly?

  • wow.! this site is great,
    it somehow helps me to learn more.

    can i ask?
    how i can i determine the numbers even and odd inputs using the pointer arithmetic?

  • WGL

    I have a question regarding a simple program which indexes using pointer arithmetic in order to reverse the case of a string. The code is this:

    Unfortunately, the output gives a completely uppercase string, “THIS IS A STRING”, rather than the inverted case where a few letters should now be lowercase. I cannot see what the problem is! The code is not complicated, but admittedly I am not used to using pointers to index an array (I am a scientist writing a program which needs to be as efficient as possible - I have been led to believe that pointer arithmetic can produce faster code).

    Any help would be appreciated!

    • Gene

      You probably discovered the reason for uppercase only a long time ago, but here’s an explanation in case you left this unsolved. The teacher in me will explode unless the answer can be revealed 😉

      You need to add “else” in between the first and second “if” clause (or you could use switch…case conditional structure instead).

      The current logic of your original code says, “if current character is uppercase, make it lowercase”, then “if current character is lowercase” (and it always will be at this point), “make it uppercase”.

      I’ve been a programmer for 23 years and I STILL sometimes miss obvious mistakes like this, so don’t feel bad about missing something so obvious.

      There is a valuable underlying principle here that might help you spot things like this in the future:

      When logical conditions are not behaving as expected, start by checking on the simplest things first, not the complicated things.

      In other words, your problem had nothing to do with pointers.

      Another way to solve the problem is to swallow your pride and ask someone else to look your code over and tell you what’s wrong with it. Just be warned that it will be embarassing! I’ve spent hours at times trying to figure out why my code isn’t working, only to watch as someone who just glances at it sees the problem instantly!

      It’s painful to do that, but you’ll help the other person feel smart and important. And that’s actually more valuable in the long run than figuring the code out yourself most of the time.

      And I agree with everybody else about this site. One of the best C++ tutorials on the web. Thanks, Alex!

      Hope this helps…

  • Dr. HaXX

    I keep seeing stuff like:

    How is that possible?

  • Matt

    I have a question about the use of the test-condition in the loop of this example and was hoping you could clear it up for me Alex.

    const int nArraySize = 7;
    char szName[nArraySize] = “Mollie”;
    int nVowels = 0;
    for (char *pnPtr = szName; pnPtr < szName + nArraySize; pnPtr++)
    switch (*pnPtr)
    case 'A':
    case 'a':
    case 'E':
    case 'e':
    case 'I':
    case 'i':
    case 'O':
    case 'o':
    case 'U':
    case 'u':

    cout << szName << " has " << nVowels << " vowels" << endl;

    If I understand this correctly, in pnPtr < szName + nArraySize;, szName is the name of the array which points to the address of element 0 in the array. nArraySize evaluates to 7, the actual size of the array which is equivalent to the pointer addition of pPtr (for the sake of making it similar to your earlier pointer arithmetic example) + 7.

    szName points to element[0] or the "M", pPtr + 1 to "o", 2 to "l", 3 to the second "l", 4 to "i", 5 to "e", 6 to the null terminator, and because the less-than sign was used instead of <=, the final element must be 1 integer higher than the size of the array so the loop ends. In this case though since you're using addresses, would it be that pPtr + 7 be the address of the next char in memory as opposed to some integer index number?

  • Matt

    Oh, In my haste writing my comment I forgot to mention that the main question was if I correctly understand how the test condition of the loop was working. That last bit at the end was something I just thought to ask at the last second.

  • sagar24


    I had a basic doubt regarding pointers. As per the pointer arithmetic, pnPtr+1 would refer to next object of the type that pnPtr points to. Thus, if pnPtr is an integer pointer than (pnPtr+1) would be (current_address_of_pnPtr + 4).
    Consider the memory block as follows :
    Memory location 0: pnPtr (Some_Int_Pointer. Assuming int takes 4 bytes)
    Memory location 4: pchPtr (Some_Char_Pointer. Assuming char takes 1 byte)
    Memory location 5: pnPtr1 (Some_Int_Pointer)

    Now when we try to access (pnPtr+2), it would try to access memory location 8 (the last byte for pnPtr1).

    Isnt that an undesirable situation. Wouldnt it return some gibberish value ?


    #include “stdafx.h”

    using namespace std;

    int main()
    const int nArraySize = 50;
    char szName[nArraySize];
    cout <> szName;
    int nVowels = 0;
    for (char *pnPtr = szName; pnPtr < szName + nArraySize; pnPtr++)
    switch (*pnPtr)
    case 'A':
    case 'a':
    case 'E':
    case 'e':
    case 'I':
    case 'i':
    case 'O':
    case 'o':
    case 'U':
    case 'u':

    cout << szName << " has " << nVowels << " vowels" << endl;
    system ("PAUSE");
    return 0;

  • ahrramin

    Why does:

    “char szName[] = “Stefan Molyneux”;

    cout << szName;"

    output: Stefan Molyneux


    "int x[] = { 1, 2, 3, 4, 5 };

    cout << x;"

    outputs the address of x?

    I tried to do the same thing with a string array:

    "string x[] = {"a", "b", "c"};

    cout << x;"

    and I got some sort of runtime error.

    • alan

      Probably not expecting a reply now, think I’ve given up with cout, if I want the address then just use the C style printf function, not familiar with using string data type yet but assume the problem with your last example however is that you assign "a", "b", "c" and I think you either mean "abc" or ‘a’, ‘b’, ‘c’

  • Chuck

    I did something similar to Chris, and obtained similar results.

    Here is my code:

    using namespace std;

    void inspectIntPointer();
    void inspectCharPointer();

    int main()
    cout << "CALLING inspectIntPointer()" << endl << endl;

    cout << "CALLING inspectCharPointer()" << endl << endl;

    return 0;

    void inspectIntPointer()
    const int nArraySize = 20;
    int nArray[nArraySize] = {11,12,13,14,15, 16,17,18,19,20, 21,22,23,24,25, 26,27,28,29,30};

    cout << "Pass *pnPtr pnPtr" << endl;
    cout << "==== ====== =====" << endl;

    int pass=1;
    for (int *pnPtr = nArray; pnPtr < nArray + nArraySize; pnPtr++)
    cout << pass << "\t\t" << *pnPtr << "\t\t\t" << pnPtr << endl << endl;
    void inspectCharPointer()
    const int nArraySize = 20;
    char szArray[nArraySize] = "abcdefghijklmnopqrs";

    cout << "Pass *pnPtr pnPtr" << endl;
    cout << "==== ====== =====" << endl;

    int pass=1;
    for (char *pnPtr = szArray; pnPtr < szArray + nArraySize; pnPtr++)
    cout << pass << "\t\t" << *pnPtr << "\t\t\t" << pnPtr << endl << endl;


    Here is the output I get:

    CALLING inspectIntPointer()

    Pass *pnPtr pnPtr
    ==== ====== =====
    1 11 0x7fff5fbff6b0

    2 12 0x7fff5fbff6b4

    3 13 0x7fff5fbff6b8

    4 14 0x7fff5fbff6bc

    5 15 0x7fff5fbff6c0

    6 16 0x7fff5fbff6c4

    7 17 0x7fff5fbff6c8

    8 18 0x7fff5fbff6cc

    9 19 0x7fff5fbff6d0

    10 20 0x7fff5fbff6d4

    11 21 0x7fff5fbff6d8

    12 22 0x7fff5fbff6dc

    13 23 0x7fff5fbff6e0

    14 24 0x7fff5fbff6e4

    15 25 0x7fff5fbff6e8

    16 26 0x7fff5fbff6ec

    17 27 0x7fff5fbff6f0

    18 28 0x7fff5fbff6f4

    19 29 0x7fff5fbff6f8

    20 30 0x7fff5fbff6fc

    CALLING inspectCharPointer()

    Pass *pnPtr pnPtr
    ==== ====== =====
    1 a abcdefghijklmnopqrs

    2 b bcdefghijklmnopqrs

    3 c cdefghijklmnopqrs

    4 d defghijklmnopqrs

    5 e efghijklmnopqrs

    6 f fghijklmnopqrs

    7 g ghijklmnopqrs

    8 h hijklmnopqrs

    9 i ijklmnopqrs

    10 j jklmnopqrs

    11 k klmnopqrs

    12 l lmnopqrs

    13 m mnopqrs

    14 n nopqrs

    15 o opqrs

    16 p pqrs

    17 q qrs

    18 r rs

    19 s s

    20 *** //*** I got an upside down question mark here! Though it didn't paste in…

    Program ended with exit code: 0

    (the formatting looked great on my debugger :p)

    I also notice that the pointer does not return a memory address to the console using COUT. I am wondering if that is a due to how COUT is interpreting the contents of the pointer, or whether the pointer is actually holding the appended string that is being sent to the console…

    I also notice two other things:

    1. When I initialize a character array to a length of ten cells, I am only able to initialize the array with 9 characters.

    char szArray[10] = "abcdefghij"; //won't work
    char szArray[10] = "abcdefghi"; //works fine

    2. I am assuming that this is due to the NULL character/pointer that is being stored in the last cell of the character array? And if so, this is why I get the upside down question mark as the last *pnPtr output on the 20th pass of the for loop when I ran my program? Should I put a condition for a break to avoid passing this to the console, or is it possible or expected to have this type of pointer located in else besides the final cell of an array?

  • youssef dirani

    Hello and thank you for the wonderful lessons.
    I have a question if you don’t mind.
    Int* pnPtr;
    *pnPtr = 3;
    Char cPtr[]=”hi mister”;
    Why cout of cPtr shows the full sentence while cout of pnPtr shows the address of the pointer?

    • Alex

      There is a special version of operator<< that knows how to output a string when it gets an object of type const char*.

      There is no special version of operator<< for other types. Other types use a generic version of operator<< that only knows how to output the address of the pointer.

  • margo

    Hello. First, I want to thank you for the wonderful tutorials.
    I have a small question: when I try to run the below code (in Visual Studio 2013), it prints out the char and a set of random symbols, and not a hex-value. But when I replace the char with an int/short/double, the code works fine and prints out the hex-value. Could you explain why it is acting like that?

Leave a Comment




5 × one =

Put C++ code inside [code][/code] tags to use the syntax highlighter