Supponiamo che io abbia 2 puntatori:
int *a = something;
int *b = something;
Se voglio confrontarli e vedere se puntano nello stesso punto, (a == b) funziona?
Supponiamo che io abbia 2 puntatori:
int *a = something;
int *b = something;
Se voglio confrontarli e vedere se puntano nello stesso punto, (a == b) funziona?
Risposte:
Sì, questa è la definizione di uguaglianza del puntatore: entrambi puntano alla stessa posizione (o sono alias del puntatore )
Per un po 'di fatti ecco il testo pertinente dalle specifiche
I puntatori a oggetti dello stesso tipo possono essere confrontati per l'uguaglianza con i risultati attesi "intuitivi":
Dal § 5.10 dello standard C ++ 11:
I puntatori dello stesso tipo (dopo le conversioni del puntatore) possono essere confrontati per l'uguaglianza. Due puntatori dello stesso tipo sono uguali se e solo se sono entrambi nulli, entrambi puntano alla stessa funzione o entrambi rappresentano lo stesso indirizzo ( 3.9.2 ).
(tralasciando i dettagli sul confronto dei puntatori al membro e / o le costanti del puntatore nullo - continuano lungo la stessa riga di 'Do What I Mean' :)
- [...] Se entrambi gli operandi sono nulli, vengono confrontati uguali. Altrimenti, se solo uno è nullo, si confrontano disuguali. [...]
L'avvertenza più `` evidente '' ha a che fare con i virtuali, e sembra essere anche la cosa logica da aspettarsi:
- [...] se uno dei due è un puntatore a una funzione membro virtuale, il risultato non è specificato. Altrimenti si confrontano uguali se e solo se si riferissero allo stesso membro dello stesso oggetto più derivato (1.8) o allo stesso sottooggetto se fossero dereferenziati con un oggetto ipotetico del tipo di classe associato. [...]
Dal § 5.9 dello standard C ++ 11:
I puntatori a oggetti o funzioni dello stesso tipo (dopo le conversioni del puntatore) possono essere confrontati, con un risultato definito come segue:
- Se due puntatori peq dello stesso tipo puntano allo stesso oggetto o funzione, o entrambi puntano uno oltre la fine dello stesso array, o sono entrambi nulli, allora
p<=q
ep>=q
entrambi restituiscono vero ep<q
edp>q
entrambi restituiscono falso.- Se due puntatori peq dello stesso tipo puntano a oggetti diversi che non sono membri dello stesso oggetto o elementi dello stesso array oa funzioni diverse, o se solo uno di essi è nullo, i risultati di
p<q,
p>q,
p<=q,
ep>=q
non sono specificati .- Se due puntatori puntano a membri di dati non statici dello stesso oggetto, o a suboggetti o elementi di matrice di tali membri, ricorsivamente, il puntatore al membro dichiarato più tardi confronta maggiore a condizione che i due membri abbiano lo stesso controllo di accesso (clausola 11) e purché la loro classe non sia un sindacato.
- Se due puntatori puntano a membri di dati non statici dello stesso oggetto con un diverso controllo di accesso (clausola 11), il risultato non è specificato.
- Se due puntatori puntano a membri dati non statici dello stesso oggetto unione, vengono confrontati uguali (dopo la conversione a
void*
, se necessario). Se due puntatori puntano a elementi della stessa matrice o uno oltre la fine della matrice, il puntatore all'oggetto con il pedice più alto confronta più alto.- Altri confronti di puntatori non sono specificati.
Quindi, se avessi:
int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined
Anche OK:
struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Ma dipende dalla something
tua domanda:
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
}
§ 20.8.5 / 8 : "Per i modelli greater
, less
, greater_equal
, e less_equal
, le specializzazioni per qualsiasi tipo di puntatore producono un ordine totale, anche se il built-in operatori <
, >
, <=
, >=
non lo fanno."
Quindi, puoi ordinare globalmente qualsiasi dispari void*
fintanto che usi std::less<>
e amici, non nudo operator<
.
int *a = arr;
linea trarrebbe vantaggio dall'inclusione di un riferimento a stackoverflow.com/questions/8412694/address-of-array ? Non sono sicuro che sia abbastanza rilevante per la domanda posta però ...
<functional>
. Aggiunto.
L' ==
operatore sui puntatori confronterà il loro indirizzo numerico e quindi determinerà se puntano allo stesso oggetto.
Per riassumere. Se vogliamo vedere se due puntatori puntano alla stessa posizione di memoria, possiamo farlo. Inoltre se vogliamo confrontare il contenuto della memoria puntato da due puntatori possiamo farlo anche noi, ricordiamoci solo di dereferenziarli prima.
Se abbiamo
int *a = something;
int *b = something;
che sono due puntatori dello stesso tipo possiamo:
Confronta indirizzo di memoria:
a==b
e confronta i contenuti:
*a==*b
Codice semplice per controllare l'alias del puntatore:
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;
}
Produzione:
p1 and p2 alias each other
p3 and p4 do not alias each other
Il confronto dei puntatori non è portabile, ad esempio in DOS diversi valori dei puntatori puntano alla stessa posizione, il confronto dei puntatori restituisce false.
/*--{++: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}--------------------------------------------------*/
Compilalo sotto Borland C 5.0, ecco il risultato:
/*--{++: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}--------------------------------------------------*/