Wskaźnik jest (w języku laika) zasadniczo wartością całkowitą dla adresu pamięci w twoim komputerze. To jest jak porównywanie liczb całkowitych.
Kemin Zhou
5
@KeminZhou: jest to prawda na większości współczesnych komputerów, ale ogólnie jest fałszywa. Nawet na starym PC AT 8086 z 1980 roku było to fałszywe
Basile Starynkevitch
109
Po trochę faktów tutaj jest odpowiedni tekst specyfikacji
Operator równości (==,! =)
Wskaźniki do obiektów tego samego typu można porównać pod kątem równości z „intuicyjnymi” oczekiwanymi wynikami:
Od § 5.10 standardu C ++ 11:
Wskaźniki tego samego typu (po konwersji wskaźnika) można porównać pod kątem równości. Dwa wskaźniki tego samego typu porównują się równo wtedy i tylko wtedy, gdy oba mają wartość null, oba wskazują na tę samą funkcję lub oba reprezentują ten sam adres ( 3.9.2 ).
(pomijając szczegóły dotyczące porównania wskaźników do składowych i / lub stałych wskaźników zerowych - kontynuują one w tym samym wierszu „Zrób to, co mam na myśli” :)
[...] Jeśli oba operandy są zerowe, porównują równe. W przeciwnym razie, jeśli tylko jeden jest zerowy, porównują nierówności. [...]
Najbardziej `` rzucające się w oczy '' zastrzeżenie dotyczy wirtualiów i wydaje się, że jest to również logiczne zastrzeżenie:
[...] jeśli którykolwiek z nich jest wskaźnikiem do wirtualnej funkcji składowej, wynik jest nieokreślony. W przeciwnym razie porównują równe wtedy i tylko wtedy, gdy odnoszą się do tego samego elementu członkowskiego tego samego najbardziej pochodnego obiektu (1.8) lub do tego samego podobiektu, gdyby zostały wyłuskane z hipotetycznym obiektem skojarzonego typu klasy. […]
Operatory relacyjne (<,>, <=,> =)
Od § 5.9 standardu C ++ 11:
Wskaźniki do obiektów lub funkcji tego samego typu (po konwersji wskaźnika) można porównać, uzyskując wynik zdefiniowany w następujący sposób:
Jeśli dwa wskaźniki p i q tego samego typu wskazują na ten sam obiekt lub funkcję, lub oba wskazują jeden za koniec tej samej tablicy lub oba mają wartość null, to p<=qi p>=qoba dają wartość true p<qi p>qobie dają false.
Jeśli dwa wskaźniki p i q tego samego typu wskazują na różne obiekty, które nie są elementami składowymi tego samego obiektu lub elementów tej samej tablicy lub różnych funkcji, lub jeśli tylko jeden z nich jest pusty, wyniki operacji p<q,p>q,p<=q,i
p>=qsą nieokreślone .
Jeśli dwa wskaźniki wskazują na niestatyczne elementy składowe danych tego samego obiektu lub podobiekty lub elementy tablicy takich elementów członkowskich, rekurencyjnie, wskaźnik do później zadeklarowanego elementu członkowskiego jest większy, pod warunkiem, że dwa elementy członkowskie mają tę samą kontrolę dostępu (klauzula 11) i pod warunkiem, że ich klasa nie jest związkiem.
Jeśli dwa wskaźniki wskazują na niestatyczne elementy składowe danych tego samego obiektu z różną kontrolą dostępu (klauzula 11), wynik jest nieokreślony.
Jeśli dwa wskaźniki wskazują na niestatyczne elementy składowe danych tego samego obiektu unii, porównują się równo (po konwersji void*, jeśli to konieczne). Jeśli dwa wskaźniki wskazują na elementy tej samej tablicy lub jeden za końcem tablicy, wskaźnik do obiektu z wyższym indeksem jest wyższy.
Inne porównania wskaźników są nieokreślone.
Tak więc, gdybyś miał:
int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined
Też dobrze:
structX {int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Ale to zależy od somethingpytania:
int g;
intmain(){
int h;
int i;
int *a = &g;
int *b = &h; // can't compare a <=> bint *c = &i; // can't compare b <=> c, or a <=> c etc.// but a==b, b!=c, a!=c etc. are supported just fine
}
Bonus: co jeszcze jest w standardowej bibliotece?
§ 20.8.5 / 8 : „W przypadku szablonów greater, less, greater_equaloraz less_equal, że specjalizacje dla każdego rodzaju wskaźnik uzyskując całkowitą zamówienia, nawet jeśli wbudowany operatorów <, >, <=, >=nie.”
Możesz więc zamówić dowolne nieparzyste void*na całym świecie , o ile używasz std::less<>i przyjaciół, a nie gołych operator<.
Dziś niepowtarzalny @JerryCoffin uświadomił mi, że biblioteka standardowa ma bardziej rygorystyczne specyfikacje dla szablonów obiektów funkcji zdefiniowanych w <functional>. Dodany.
Jest to trochę bardziej skomplikowane, jeśli w grę wchodzi wielokrotne dziedziczenie.
fredoverflow
17
Podsumowując. Jeśli chcemy zobaczyć, czy dwa wskaźniki wskazują na tę samą lokalizację pamięci, możemy to zrobić. Również jeśli chcemy porównać zawartość pamięci wskazywaną przez dwa wskaźniki, możemy to również zrobić, po prostu pamiętajmy, aby najpierw je wyodrębnić.
Jeśli mamy
int *a = something;
int *b = something;
które są dwoma wskaźnikami tego samego typu, możemy:
intmain(){
int a = 10, b = 20;
int *p1, *p2, *p3, *p4;
p1 = &a;
p2 = &a;
if(p1 == p2){
std::cout<<"p1 and p2 alias each other"<<std::endl;
}
else{
std::cout<<"p1 and p2 do not alias each other"<<std::endl;
}
//------------------------
p3 = &a;
p4 = &b;
if(p3 == p4){
std::cout<<"p3 and p4 alias each other"<<std::endl;
}
else{
std::cout<<"p3 and p4 do not alias each other"<<std::endl;
}
return0;
}
Wynik:
p1 and p2 alias each other
p3 and p4 donot alias each other
Porównywanie wskaźników nie jest przenośne, na przykład w DOS różne wartości wskaźników wskazują na tę samą lokalizację, porównanie wskaźników zwraca fałsz.
Odpowiedzi:
Tak, to jest definicja równości wskaźników: oba wskazują tę samą lokalizację (lub są aliasami wskaźników )
źródło
Po trochę faktów tutaj jest odpowiedni tekst specyfikacji
Operator równości (==,! =)
Wskaźniki do obiektów tego samego typu można porównać pod kątem równości z „intuicyjnymi” oczekiwanymi wynikami:
Od § 5.10 standardu C ++ 11:
Operatory relacyjne (<,>, <=,> =)
Od § 5.9 standardu C ++ 11:
Tak więc, gdybyś miał:
int arr[3]; int *a = arr; int *b = a + 1; assert(a != b); // OK! well defined
Też dobrze:
struct X { int x,y; } s; int *a = &s.x; int *b = &s.y; assert(b > a); // OK! well defined
Ale to zależy od
something
pytania:int g; int main() { int h; int i; int *a = &g; int *b = &h; // can't compare a <=> b int *c = &i; // can't compare b <=> c, or a <=> c etc. // but a==b, b!=c, a!=c etc. are supported just fine }
Bonus: co jeszcze jest w standardowej bibliotece?
§ 20.8.5 / 8 : „W przypadku szablonów
greater
,less
,greater_equal
orazless_equal
, że specjalizacje dla każdego rodzaju wskaźnik uzyskując całkowitą zamówienia, nawet jeśli wbudowany operatorów<
,>
,<=
,>=
nie.”Możesz więc zamówić dowolne nieparzyste
void*
na całym świecie , o ile używaszstd::less<>
i przyjaciół, a nie gołychoperator<
.źródło
int *a = arr;
wiersz skorzystałby na dołączeniu odwołania do stackoverflow.com/questions/8412694/address-of-array ? Nie jestem pewien, czy jest to wystarczające do zadanego pytania ...<functional>
. Dodany.==
Operator na wskaźnikach będzie porównać swój adres numeryczny, a więc ustalić, czy wskazują one na tym samym obiekcie.źródło
Podsumowując. Jeśli chcemy zobaczyć, czy dwa wskaźniki wskazują na tę samą lokalizację pamięci, możemy to zrobić. Również jeśli chcemy porównać zawartość pamięci wskazywaną przez dwa wskaźniki, możemy to również zrobić, po prostu pamiętajmy, aby najpierw je wyodrębnić.
Jeśli mamy
int *a = something; int *b = something;
które są dwoma wskaźnikami tego samego typu, możemy:
Porównaj adres pamięci:
i porównaj zawartość:
źródło
Prosty kod do sprawdzania aliasingu wskaźnika:
int main () { int a = 10, b = 20; int *p1, *p2, *p3, *p4; p1 = &a; p2 = &a; if(p1 == p2){ std::cout<<"p1 and p2 alias each other"<<std::endl; } else{ std::cout<<"p1 and p2 do not alias each other"<<std::endl; } //------------------------ p3 = &a; p4 = &b; if(p3 == p4){ std::cout<<"p3 and p4 alias each other"<<std::endl; } else{ std::cout<<"p3 and p4 do not alias each other"<<std::endl; } return 0; }
Wynik:
p1 and p2 alias each other p3 and p4 do not alias each other
źródło
Porównywanie wskaźników nie jest przenośne, na przykład w DOS różne wartości wskaźników wskazują na tę samą lokalizację, porównanie wskaźników zwraca fałsz.
/*--{++:main.c}--------------------------------------------------*/ #include <dos.h> #include <stdio.h> #include <stdlib.h> int main(void) { int val_a = 123; int * ptr_0 = &val_a; int * ptr_1 = MK_FP(FP_SEG(&val_a) + 1, FP_OFF(&val_a) - 16); printf(" val_a = %d -> @%p\n", val_a, (void *)(&val_a)); printf("*ptr_0 = %d -> @%p\n", *ptr_0, (void *)ptr_0); printf("*ptr_1 = %d -> @%p\n", *ptr_1, (void *)ptr_1); /* Check what returns the pointers comparison: */ printf("&val_a == ptr_0 ====> %d\n", &val_a == ptr_0); printf("&val_a == ptr_1 ====> %d\n", &val_a == ptr_1); printf(" ptr_0 == ptr_1 ====> %d\n", ptr_0 == ptr_1); printf("val_a = %d\n", val_a); printf(">> *ptr_0 += 100;\n"); *ptr_0 += 100; printf("val_a = %d\n", val_a); printf(">> *ptr_1 += 500;\n"); *ptr_1 += 500; printf("val_a = %d\n", val_a); return EXIT_SUCCESS; } /*--{--:main.c}--------------------------------------------------*/
Skompiluj go pod Borland C 5.0, oto wynik:
/*--{++:result}--------------------------------------------------*/ val_a = 123 -> @167A:0FFE *ptr_0 = 123 -> @167A:0FFE *ptr_1 = 123 -> @167B:0FEE &val_a == ptr_0 ====> 1 &val_a == ptr_1 ====> 0 ptr_0 == ptr_1 ====> 0 val_a = 123 >> *ptr_0 += 100; val_a = 223 >> *ptr_1 += 500; val_a = 723 /*--{--:result}--------------------------------------------------*/
źródło