Jak zwiększyć adres wskaźnika i wartość wskaźnika?

Załóżmy,

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

Co i jak będzie robił poniższy kod?

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

Wiem, że to trochę niechlujne, jeśli chodzi o kodowanie, ale chcę wiedzieć, co naprawdę się stanie, gdy będziemy kodować w ten sposób.

Uwaga: Załóżmy, że adres a=5120300 jest przechowywany w wskaźniku p, którego adres to 3560200. Jaka będzie wartość p & a Po wykonaniu każdego polecenia?

 101
Author: Thomas131, 2011-11-21

5 answers

Po pierwsze, operator ++ ma pierwszeństwo przed operatorem*, a operatory () mają pierwszeństwo przed wszystkim innym.

Po Drugie, operator liczby ++jest taki sam jak operator liczby++, jeśli nie przypisujesz ich do niczego. Różnica polega na tym, że liczba++ Zwraca liczbę i następnie zwiększa liczbę, a liczba ++najpierw zwiększa, a następnie zwraca ją.

Po Trzecie, zwiększając wartość wskaźnika, zwiększasz go o rozmiar jego zawartości, czyli jesteś zwiększając go tak, jakbyś iterację w tablicy.

Podsumowując to wszystko:

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 of ptr is incremented
++(*ptr); // The value of ptr is incremented
++*(ptr); // The value of 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 of 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 get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault
Ponieważ jest tu wiele spraw, mogłem popełnić jakiś błąd, proszę mnie poprawić, jeśli się mylę.

EDIT:

Więc się myliłem, pierwszeństwo jest trochę bardziej skomplikowane niż to, co napisałem, zobacz to tutaj: http://en.cppreference.com/w/cpp/language/operator_precedence

 187
Author: felipemaia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 15:52:56

Sprawdził program i wyniki są następujące:

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
 15
Author: Sujith R Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-21 10:16:21

Poniżej znajduje się instancja różnych sugestii "po prostu wydrukuj". Uważam to za pouczające.

#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;
}

Zwraca

(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

Rzuciłem adresy wskaźnikowe na int S, aby można je było łatwo porównać.

Skompilowałem go z GCC.

 5
Author: Rico Picone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 01:52:00

W odniesieniu do "Jak zwiększyć adres wskaźnika i wartość wskaźnika?" myślę, że ++(*p++); jest właściwie dobrze zdefiniowany i robi to, o co prosisz, np.:

#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;
}

Nie modyfikuje tego samego dwa razy przed punktem sekwencji. Nie sądzę, aby był to dobry styl do większości zastosowań - jest trochę zbyt tajemniczy jak na moje upodobania.

 3
Author: Flexo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-21 10:24:33
        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);
 1
Author: Abhishek D K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-24 06:39:46