Предположим, у меня есть 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 ).
(опуская подробности сравнения указателей на константы члена и / или нулевого указателя - они продолжаются в той же строке «Do What I Mean» :)
- [...] Если оба операнда равны нулю, они сравниваются как равные. В противном случае, если только один из них равен нулю, они сравнивают неравные. [...]
Самая «заметная» оговорка связана с виртуальными машинами, и этого, похоже, тоже логично ожидать:
- [...] если любой из них является указателем на виртуальную функцию-член, результат не указан. В противном случае они сравнивают равными тогда и только тогда, когда они будут ссылаться на один и тот же член одного и того же самого производного объекта (1.8) или на один и тот же подобъект, если они были разыменованы с гипотетическим объектом соответствующего типа класса. [...]
Из § 5.9 стандарта C ++ 11:
Указатели на объекты или функции одного и того же типа (после преобразования указателя) можно сравнивать с результатом, определяемым следующим образом:
- Если два указателя р и д из одной и той же точки типа к тому же объекту или функции, или как точка одной мимо конца того же массива, или оба нуль, то
p<=q
иp>=q
как выход истинного иp<q
иp>q
одновременно выход ложным.- Если два указателя p и q одного и того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или разных функций, или если только один из них имеет значение NULL, результаты
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}--------------------------------------------------*/