2017-11-10 162 views
7

Jeśli mam dwie zmienne wskaźnikowe, aib, co to znaczy używać instrukcji "a < b"? Czy powinno to porównywać wartości ich adresów pamięci? Jeśli tak, jaka byłaby kolejność adresów pamięci w komputerze?Co to znaczy porównywanie wskaźników za pomocą operatorów relacyjnych?

+1

Podejrzewam, że coś takiego będzie bardzo specyficzne dla języka. W niektórych naiwnych przypadkach wskaźniki są dosłownie (lub mogą być traktowane jak pamięć). W innych przypadkach są to bardzo specyficzne typy, a operatorzy będą zachowywać się specyficznie. – jdv

+0

Powiązane [Biorąc pod uwagę, że p jest wskaźnikiem jest "p> nullptr" dobrze sformułowane?] (Https://stackoverflow.com/q/26590267/1708801) –

+0

Moja odpowiedź do [Uzasadnienie do porównania wskaźnika poza tablicą do UB ] (https://stackoverflow.com/a/31151779/1708801) jest również powiązany. –

Odpowiedz

6

W językach C i C++ porównywanie wskaźników za pomocą operatorów relacyjnych jest dozwolone w przypadku, gdy masz dwa wskaźniki w tej samej tablicy i chcesz zobaczyć ich względną kolejność (istnieje wyjątek od tej reguły, o którym powiem w niewielkim stopniu kawałek). Na przykład, wyobraźmy sobie, że p i q każdy punkt gdzieś w środku tablicy arr, jak pokazano poniżej:

  int arr[9]; 
      int* p = &arr[1]; 
      int* q = &arr[4]; 

    +-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
arr |  |  |  |  |  |  |  |  |  | 
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
      ^    ^
      |     | 
      p     q 

W tym przypadku, wyrażenie p < q pyta „jest indeksem w tablicy, która p wskazuje na niższy niż indeks w tablicy, który wskazuje na q? " W powyższym kontekście odpowiedź brzmi "tak". Jeśli p i q zostały odwrócone lub wskazały dokładnie ten sam element, odpowiedź brzmiałaby "nie".

Standardy językowe w językach C i C++ mówią, że wynik porównania wskaźników, które nie wskazują tej samej tablicy, jest nieokreślony, co intuicyjnie ma sens, ponieważ niepowiązane obiekty mogą być rozmieszczone dość losowo w pamięci lub być powiązane w sposób zależny od implementacji (czy twój stos rośnie lub spada?)

Jedynym wyjątkiem jest to, że możesz porównywać wskaźnik jednego obiektu za koniec tablicy ze wskaźnikiem w szyk. Na przykład, spójrz na tej konfiguracji:

  int arr[9]; 
      int* p = &arr[1]; 
      int* q = &arr[9]; 

    +-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
arr |  |  |  |  |  |  |  |  |  | 
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
      ^           ^
      |            | 
      p            q 

Tutaj q nie wskazuje na tablicy arr. Jednak specyfikacja językowa pozwala ci bezpiecznie porównać p i q. Dlatego na przykład można bezpiecznie używać tej pętli w stylu iteratora w C++:

for (int* itr = arr; itr != arr + /* arr's size */; itr++) { 
    ... 
} 
+0

Aby dodać: "... w przypadku, gdy masz dwa wskaźniki w tej samej tablicy _lub obiekt_". Ta dyskusja tablicowa odnosi się również do pojedynczego obiektu, tak jakby była tablicą jednego. 'some_type x;' '& x + 1> & x' jest dobrze zdefiniowane. §6.5.8 4 – chux

+0

Można również porównywać wskaźniki do elementów tego samego obiektu zbiorczego, np. Wskaźnik do 'int a' w obiekcie struct ze wskaźnikiem do' double b' w tym samym obiekcie. –

+0

@EricPostpischil Nie wiedziałem, że możesz to zrobić. Zakładam, że musisz użyć jakiegoś smaku wskaźników "char *" na obiektach różnych typów, aby uniknąć poważnych naruszeń aliasingu? – templatetypedef