How to increment a pointer address and pointer's value?
Asked Answered
B

5

132

Let us assume,

int *p;
int a = 100;
p = &a;

What will the following code actually do and how?

p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);

I know, this is kind of messy in terms of coding, but I want to know what will actually happen when we code like this.

Note : Lets assume that the address of a=5120300, it is stored in pointer p whose address is 3560200. Now, what will be the value of p & a after the execution of each statement?

Brilliant answered 21/11, 2011 at 6:23 Comment(3)
Well .. why not simply try it and see? printf will print a pointer with %pMarlie
If you're curious about behavior, just play around with it. Just write a simple c program that goes through all of these use cases and see if it makes sense to you.Leonie
@AndersK. Maybe the OP expects undefined behavior? ...Or maybe not.Privative
L
261

First, the ++ operator takes precedence over the * operator, and the () operators take precedence over everything else.

Second, the ++number operator is the same as the number++ operator if you're not assigning them to anything. The difference is number++ returns number and then increments number, and ++number increments first and then returns it.

Third, by increasing the value of a pointer, you're incrementing it by the sizeof its contents, that is you're incrementing it as if you were iterating in an array.

So, to sum it all up:

ptr++;    // Pointer moves to the next int position (as if it was an array)
++ptr;    // Pointer moves to the next int position (as if it was an array)
++*ptr;   // The value pointed at by ptr is incremented
++(*ptr); // The value pointed at by ptr is incremented
++*(ptr); // The value pointed at by ptr is incremented
*ptr++;   // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value pointed at by ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr;   // Pointer moves to the next int position, and then gets accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then gets accessed, with your code, segfault

As there are a lot of cases in here, I might have made some mistake, please correct me if I'm wrong.

EDIT:

So I was wrong, the precedence is a little more complicated than what I wrote, view it here: http://en.cppreference.com/w/cpp/language/operator_precedence

Lakieshalakin answered 21/11, 2011 at 6:34 Comment(4)
*ptr++, the value is not incremented, the pointer is. These unary operators have the same precedence but they are evaluated right-to-left. The code means "take the contents from where ptr points at, then increment ptr". It is very common C code (and yes, quite confusing). Please correct this and I'll remove the downvote. Same for *(ptr)++, the parenthesis does nothing.Herbst
@Herbst Hi, is the answer above corrected now? Thanks.Leyva
@Leyva The first sentence is still completely wrong, postfix ++ takes precedence over unary * which has the same precedence as prefix ++. Apart from that, it seems ok.Herbst
@Lakieshalakin Are you sure that it will segfault? Maybe its just undefined behaviour?Tippett
S
18

checked the program and the results are as,

p++;    // use it then move to next int position
++p;    // move to next int and then use it
++*p;   // increments the value by 1 then use it 
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++;   // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p;   // moves to the next int location then use that value
*(++p); // moves to next location then use that value
Slangy answered 23/3, 2015 at 6:35 Comment(2)
@alex use it means for example, consider statement, 'int *a = p++;' Here first value of pointer 'p' will be used to and after that p will move to next position. So in effect after executing above statement 'a' will have address of previous location pointed by 'p' and 'p' will be pointing to next position. That is first use the value of 'p' for the assignment expression as above and then increment value of 'p' to point to next positionSlangy
In short, I think he uses the phrase "use it" for the more formal term "assign". That is all.Hyetology
A
7

The following is an instantiation of the various "just print it" suggestions. I found it instructive.

#include "stdio.h"

int main() {
    static int x = 5;
    static int *p = &x;
    printf("(int) p   => %d\n",(int) p);
    printf("(int) p++ => %d\n",(int) p++);
    x = 5; p = &x;
    printf("(int) ++p => %d\n",(int) ++p);
    x = 5; p = &x;
    printf("++*p      => %d\n",++*p);
    x = 5; p = &x;
    printf("++(*p)    => %d\n",++(*p));
    x = 5; p = &x;
    printf("++*(p)    => %d\n",++*(p));
    x = 5; p = &x;
    printf("*p++      => %d\n",*p++);
    x = 5; p = &x;
    printf("(*p)++    => %d\n",(*p)++);
    x = 5; p = &x;
    printf("*(p)++    => %d\n",*(p)++);
    x = 5; p = &x;
    printf("*++p      => %d\n",*++p);
    x = 5; p = &x;
    printf("*(++p)    => %d\n",*(++p));
    return 0;
}

It returns

(int) p   => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p      => 6
++(*p)    => 6
++*(p)    => 6
*p++      => 5
(*p)++    => 5
*(p)++    => 5
*++p      => 0
*(++p)    => 0

I cast the pointer addresses to ints so they could be easily compared.

I compiled it with GCC.

Asleep answered 5/2, 2018 at 1:27 Comment(1)
I would change this to include the value of x and p after the operation.Llama
D
4

With regards to "How to increment a pointer address and pointer's value?" I think that ++(*p++); is actually well defined and does what you're asking for, e.g.:

#include <stdio.h>

int main() {
  int a = 100;
  int *p = &a;
  printf("%p\n",(void*)p);
  ++(*p++);
  printf("%p\n",(void*)p);
  printf("%d\n",a);
  return 0;
}

It's not modifying the same thing twice before a sequence point. I don't think it's good style though for most uses - it's a little too cryptic for my liking.

Disheveled answered 21/11, 2011 at 10:24 Comment(1)
Actually, the parentheses are unnecessary: ++*p++ will successfully increment both value and pointer (postfix ++ binds stronger than dereference *, and that happens before the prefix ++ due to order). The parentheses are only necessary when you need the value before incrementing it (*p++)++. If you go all-prefix, ++*++p will work just fine without parentheses as well (but increment the value that is pointed at after the pointer increment).Kavita
B
3
        Note:
        1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
        2) in this case Associativity is from **Right-Left**

        important table to remember in case of pointers and arrays: 

        operators           precedence        associativity

    1)  () , []                1               left-right
    2)  *  , identifier        2               right-left
    3)  <data type>            3               ----------

        let me give an example, this might help;

        char **str;
        str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
        str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
        str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char

        strcpy(str[0],"abcd");  // assigning value
        strcpy(str[1],"efgh");  // assigning value

        while(*str)
        {
            cout<<*str<<endl;   // printing the string
            *str++;             // incrementing the address(pointer)
                                // check above about the prcedence and associativity
        }
        free(str[0]);
        free(str[1]);
        free(str);
Bluebird answered 24/6, 2018 at 6:4 Comment(2)
What is asociativity?Monteverdi
in the code you can see the *str++, now here both * and ++ have same precedence( same priority in layman's term) and also *str++ are not seperated using parentheses like *(str++) or (*str)++, so it becomes necessary how it should be evaluated . so right to left means ( x = str++) and then (y = *x)Bluebird

© 2022 - 2024 — McMap. All rights reserved.