Припустимо, у мене є 2 вказівники:
int *a = something;
int *b = something;
Якщо я хочу порівняти їх і подивитися, чи вказують вони на одне і те ж місце (a == b), працює?
Припустимо, у мене є 2 вказівники:
int *a = something;
int *b = something;
Якщо я хочу порівняти їх і подивитися, чи вказують вони на одне і те ж місце (a == b), працює?
Відповіді:
Так, це визначення рівності покажчика: вони обидва вказують на одне і те ж розташування (або є псевдонімами вказівника )
Для кількох фактів наведемо відповідний текст із специфікацій
Покажчики на об'єкти одного типу можна порівняти за рівністю з "інтуїтивними" очікуваними результатами:
З § 5.10 стандарту C ++ 11:
Покажчики одного типу (після перетворення покажчиків) можна порівняти за рівністю. Два покажчики одного типу порівнюють рівні тоді і тільки тоді, коли обидва вони є нульовими, обидва вказують на одну і ту ж функцію, або обидва представляють одну і ту ж адресу ( 3.9.2 ).
(залишаючи деталі щодо порівняння покажчиків з константами члена та / або нульового вказівника - вони продовжують той самий рядок "Робити те, що я маю на увазі" :)
- [...] Якщо обидва операнди є нульовими, вони порівнюються рівними. В іншому випадку, якщо лише один є нульовим, вони порівнюють нерівне. [...]
Найбільш помітне застереження пов’язане з віртуальними програмами, і, схоже, логічно це також очікувати:
- [...] якщо будь-який є вказівником на функцію віртуального члена, результат не вказаний. В іншому випадку вони порівнюють рівне тоді і тільки тоді, коли вони посилалися б на одного і того ж члена того самого найбільш похідного об'єкта (1.8) або на той самий суб'єкт, якщо б вони були визначені гіпотетичним об'єктом відповідного типу класу. [...]
З § 5.9 стандарту C ++ 11:
Покажчики на об'єкти або функції одного типу (після перетворення покажчиків) можна порівнювати, і результат визначається наступним чином:
- Якщо два вказівники p і q одного і того ж типу вказують на один і той же об'єкт або функцію, або обидва вказують один за одним кінцем одного масиву, або обидва є нульовими, тоді
p<=q
іp>=q
обидва дають true,p<q
іp>q
обидва дають false.- Якщо два вказівники p і q одного і того ж типу вказують на різні об'єкти, які не є членами одного і того ж об'єкта або елементів одного масиву або різних функцій, або якщо лише один з них є нульовим, результати
p<q,
p>q,
p<=q,
таp>=q
не вказані .- Якщо два покажчики рекурсивно вказують на нестатичні члени даних одного і того ж об'єкта, або на суб'єкти або елементи масиву таких членів, вказівник на пізніше оголошений член порівнює більше за умови, що два члени мають однаковий контроль доступу (пункт 11) і за умови, що їхній клас не є об’єднанням.
- Якщо два вказівники вказують на нестатичні члени даних одного і того ж об'єкта з різним контролем доступу (пункт 11), результат не вказаний.
- Якщо два вказівники вказують на нестатичні члени даних одного об'єкта об'єднання, вони порівнюють рівні (після перетворення в
void*
, якщо потрібно). Якщо два вказівники вказують на елементи одного і того ж масиву або один за кінцем масиву, вказівник на об'єкт із старшим індексом порівнюється вище.- Інші порівняння покажчиків не вказані.
Отже, якщо у вас було:
int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined
Також добре:
struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Але це залежить від something
Вашого запитання:
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 : «Для шаблонів greater
, less
, greater_equal
і less_equal
, спеціалізації для будь-якого типу покажчика дають повний порядок, навіть якщо вбудовані оператори <
, >
, <=
, >=
цього не роблять.»
Отже, ви можете замовити будь-яке непарне void*
, якщо ви використовуєте std::less<>
друзів, а не голі operator<
.
int *a = arr;
виграє рядок включенням посилання на stackoverflow.com/questions/8412694/address-of-array ? Я не впевнений, наскільки це відповідає запитанню, хоча ...
<functional>
. Додано.
==
Оператор покажчиків буде порівнювати їх числову адресу і , отже , визначити , якщо вони вказують на той же об'єкт.
Підсумовуючи. Якщо ми хочемо перевірити, чи вказують два вказівники на одне і те ж місце в пам'яті, ми можемо це зробити. Крім того, якщо ми хочемо порівняти вміст пам'яті, на яку вказують два вказівники, ми можемо зробити це теж, просто пам'ятаємо, щоб спершу їх розмежувати.
Якщо маємо
int *a = something;
int *b = something;
які є двома покажчиками одного типу, ми можемо:
Порівняйте адресу пам'яті:
a==b
та порівняти вміст:
*a==*b
Простий код для перевірки псевдонімів покажчика:
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;
}
Вихід:
p1 and p2 alias each other
p3 and p4 do not alias each other
Порівняння покажчиків не є портативним, наприклад, у DOS різні значення покажчиків вказують на одне і те ж розташування, порівняння покажчиків повертає значення 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}--------------------------------------------------*/
Складіть його під Borland C 5.0, ось результат:
/*--{++: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}--------------------------------------------------*/