Załóżmy,
int *p;
int a = 100;
p = &a;
Co właściwie zrobi poniższy kod i jak?
p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);
Wiem, że jest to trochę bałaganiarskie, jeśli chodzi o kodowanie, ale chcę wiedzieć, co się właściwie stanie, gdy będziemy pisać w ten sposób.
Uwaga: Załóżmy, że adres a=5120300
, jest przechowywany we wskaźniku, p
którego adresem jest 3560200
. Jaka będzie wartość p & a
po wykonaniu każdej instrukcji?
printf
wypisze wskaźnik z% pOdpowiedzi:
Po pierwsze, operator ++ ma pierwszeństwo przed operatorem *, a operatory () mają pierwszeństwo przed wszystkim innym.
Po drugie, operator ++ liczb jest taki sam jak operator ++ liczby, jeśli nie przypisujesz ich do niczego. Różnica polega na tym, że liczba ++ zwraca liczbę, a następnie zwiększa liczbę, a ++ najpierw zwiększa liczbę, a następnie zwraca.
Po trzecie, zwiększając wartość wskaźnika, zwiększasz go o rozmiar jego zawartości, czyli zwiększasz go tak, jakbyś wykonywał iterację w tablicy.
Podsumowując:
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 przypadków, mogłem popełnić jakiś błąd, popraw mnie, jeśli się mylę.
EDYTOWAĆ:
Więc pomyliłem się, pierwszeństwo jest trochę bardziej skomplikowane niż to, co napisałem, zobacz to tutaj: http://en.cppreference.com/w/cpp/language/operator_precedence
źródło
sprawdziłem program i wyniki są jak,
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
źródło
Poniżej znajduje się zestawienie różnych sugestii „po prostu wydrukuj”. Uznałem 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; }
Wraca
(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
Rzucam adresy wskaźników do
int
s, aby można je było łatwo porównać.Skompilowałem to za pomocą GCC.
źródło
W odniesieniu do "Jak zwiększyć adres wskaźnika i wartość wskaźnika?" Myślę, że
++(*p++);
jest to właściwie dobrze zdefiniowane 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ę, żeby to był dobry styl dla większości zastosowań - jest trochę zbyt tajemniczy jak na mój gust.
źródło
++*p++
z powodzeniem zwiększą zarówno wartość, jak i wskaźnik (++
wiązanie postfiksowe jest silniejsze niż dereferencja*
, a dzieje się to przed prefiksem z++
powodu kolejności). Nawiasy są potrzebne tylko wtedy, gdy potrzebujesz wartości przed jej zwiększeniem(*p++)++
. Jeśli wybierzesz all-prefix,++*++p
będzie działać dobrze również bez nawiasów (ale zwiększ wartość wskazaną po inkrementacji wskaźnika).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);
źródło