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


98

Załóżmy,

Co właściwie zrobi poniższy kod i jak?

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, pktórego adresem jest 3560200. Jaka będzie wartość p & apo wykonaniu każdej instrukcji?


3
dlaczego po prostu nie uruchomisz go w debugerze?
AndersK

24
Cóż… dlaczego po prostu nie spróbować i zobaczyć? printfwypisze wskaźnik z% p
Brian Roach

Jeśli jesteś ciekawy zachowania, po prostu pobaw się nim. Po prostu napisz prosty program w C, który przejdzie przez wszystkie te przypadki użycia i sprawdź, czy ma to dla Ciebie sens.
Cyrus

@AndersK. Może PO oczekuje niezdefiniowanego zachowania? ...Albo może nie.
Mateen Ulhaq

Odpowiedzi:


182

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:

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


6
* ptr ++, wartość nie jest zwiększana, wskaźnik jest. Te operatory jednoargumentowe mają ten sam priorytet, ale są oceniane od prawej do lewej. Kod oznacza „weź zawartość, skąd wskazuje ptr, a następnie zwiększ ptr”. Jest to bardzo powszechny kod C (i tak, dość mylący). Popraw to, a usunę głos przeciw. To samo dla * (ptr) ++, nawias nic nie robi.
Lundin

Dziękuję bardzo Lundin, czy przegapiłem coś jeszcze?
felipemaia

@Lundin Cześć, czy powyższa odpowiedź jest teraz poprawiona? Dzięki.
Unheilig

4
@Unheilig Pierwsze zdanie jest nadal całkowicie błędne, postfix ++ ma pierwszeństwo przed jednoargumentowym *, który ma taki sam priorytet jak przedrostek ++. Poza tym wydaje się w porządku.
Lundin

4
@felipemaia Czy na pewno będzie segfault? Może to po prostu niezdefiniowane zachowanie?
jotik

15

sprawdziłem program i wyniki są jak,


2
@alex użyj tego, co oznacza na przykład, rozważ instrukcję, 'int * a = p ++;' Tutaj pierwsza wartość wskaźnika „p” zostanie wykorzystana, a następnie p przejdzie do następnej pozycji. W efekcie po wykonaniu powyższej instrukcji 'a' będzie miał adres poprzedniej lokalizacji wskazywany przez 'p', a 'p' będzie wskazywać na następną pozycję. To znaczy najpierw użyj wartości „p” dla wyrażenia przypisania jak powyżej, a następnie
zwiększ

Krótko mówiąc, myślę, że używa wyrażenia „użyj go” dla bardziej formalnego terminu „przydziel”. To wszystko.
Apekshik Panigrahi

4

Poniżej znajduje się zestawienie różnych sugestii „po prostu wydrukuj”. Uznałem to za pouczające.

Wraca

Rzucam adresy wskaźników do int s, aby można je było łatwo porównać.

Skompilowałem to za pomocą GCC.


1
Zmieniłbym to, aby uwzględnić wartości x i p po operacji.
NetJohn

3

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 .:

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.


W rzeczywistości nawiasy są niepotrzebne: ++*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, ++*++pbędzie działać dobrze również bez nawiasów (ale zwiększ wartość wskazaną po inkrementacji wskaźnika).
cmaster

1

Co to jest asocjatywność?
71GA

1
w kodzie widać * str ++, teraz zarówno * i ++ mają ten sam priorytet (ten sam priorytet w terminach laika), a także * str ++ nie są oddzielane za pomocą nawiasów takich jak * (str ++) lub (* str) ++, więc konieczne staje się, jak należy to oceniać. więc od prawej do lewej oznacza (x = str ++), a następnie (y = * x)
Abhishek DK,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.