2015-08-02 11 views
6

C++ Programming Language 3rd edition przez Stroustrup mówi, żeCzy porównanie wskaźników jest niezdefiniowane lub nieokreślone w C++?

odejmowanie wskaźników jest zdefiniowany tylko wtedy, gdy oba wskaźniki wskazują na elementami tej samej tablicy (choć język ma szybki sposób zapewniając, że jest walizka). Odejmując jeden wskaźnik od drugiego, wynikiem jest liczba elementów tablicy między dwoma wskaźnikami (liczba całkowita). Można dodać liczbę całkowitą do wskaźnika lub odjąć liczbę całkowitą od wskaźnika; w obu przypadkach wynikiem jest wartość wskaźnika. Jeśli ta wartość nie wskazuje na element tej samej tablicy co oryginalny wskaźnik lub poza nią, wynikiem użycia tej wartości jest niezdefiniowana wartość .

Na przykład:

void f() 
{ 
    int v1 [10]; 
    int v2 [10]; 
    int i1 = &v1[5] - &v1[3]; // i1 = 2 
    int i2 = &v1[5] - &v2[3]; // result undefined 
} 

czytałem o unspecified behavior na Wikipedia. Mówi, że w C i C++ porównanie wskaźników do obiektów jest ściśle określone, jeśli wskaźniki wskazują na elementy tego samego obiektu lub elementy tej samej tablicy.

Przykład:

int main(void) 
{ 
    int a = 0; 
    int b = 0; 
    return &a < &b; /* unspecified behavior in C++, undefined in C */ 
} 

Tak, jestem zdezorientowany. Który jest prawidłowy? Wikipedia czy książka Stroustrupa? Co mówi o tym standard C++?

Popraw mnie Jeśli coś nie rozumiem.

+0

Nie widzę 2 fragmentów jako sprzeczne. Czy możesz wyjaśnić swoje zamieszanie? – Amit

+3

Stroustrup odnosi się do wskaźnika * odejmowanie * (zwanego także wskaźnikiem * różnicowanie *), a przykład pokazuje obliczenie różnicy. Artykuł, który cytujesz z Wiki, odnosi się do wskaźnika logicznego * porównanie *. – WhozCraig

Odpowiedz

10

Należy zauważyć, że odejmowanie wskaźnika i porównywanie wskaźnika to różne operacje z różnymi regułami.

C++ 14 5,6/6, w odejmowanie wskazówek:

ile oba wskaźniki wskazują elementy tego samego obiektu matrycy lub jednej ostatnim elementem obiektu tablicy, działanie jest nieokreślona.

C++ 14 5,9/3-4:

Porównując wskaźniki do obiektów jest zdefiniowany w następujący sposób:

  • Jeśli dwa wskaźniki punkt różnych elementów tego samego szeregu, lub do jego podobieństw, wskaźnik do elementu o wyższym indeksie dolnym jest większy.

  • Jeśli jeden wskaźnik wskazuje na element tablicy lub na jej podobiekt, a inny wskaźnik wskazuje jeden za ostatnim elementem tablicy, ten ostatni porównuje większy.

  • Jeśli dwa wskaźniki wskazują na różne niestatyczne elementy danych tego samego obiektu lub na podobiekty takich elementów, to rekurencyjnie wskaźnik do później zadeklarowanego elementu porównuje większy pod warunkiem, że dwa elementy mają tę samą kontrolę dostępu i ich klasa nie jest związkiem.

Jeśli dwa operandy p i q porównanie równe (5,10) p<=q i p>=q zarówno wydajność true i p<q i p>q zarówno wydajność fałszywe. W przeciwnym razie, jeśli wskaźnik p porównuje większy niż wskaźnik q, p>=q, p>q, q<=p i q<p wszystko uzyskując true i p<=q, p<q, q>=p i q>p wszystko uzyskując false. W przeciwnym razie wynik każdego z operatorów jest nieokreślony.

+0

W ostatnim zdaniu "W przeciwnym razie wynik każdego z operatorów jest nieokreślony." Dlaczego powinien być nieokreślony zamiast niezdefiniowanego? czy to dlatego, że standard definiuje, że możliwe wyniki są prawdziwe tylko z powodu fałszu, więc żadne inne zachowania nie mogą się zdarzyć? –

+0

@LorenzoBelli "undefined" jest o wiele bardziej poważnym błędem niż "nieokreślony", dosłownie wszystko może się zdarzyć, włącznie z awarią twojego programu. Przy nieokreślonym zachowaniu, jedynym problemem jest to, że nie wiesz, czy wynik będzie "prawdziwy" czy "fałsz" - a kompilator może określić to zachowanie bardziej rygorystycznie niż wymaga tego standard. Zasadniczo autorzy specyfikacji chcą dopuszczać dobrze zachowane programy i określać nieokreślone zachowanie tylko wtedy, gdy jest to absolutnie konieczne. –

+0

@LorenzoBelli Również operator musi zwrócić tę samą wartość, jeśli porównanie zostanie wykonane dwukrotnie w przypadku Nieokreślonego zachowania. Ale w przypadku UB każde porównanie może zwracać wartość true/false niezależnie. –

Powiązane problemy