Указатель - это (в терминологии непрофессионала) по сути целочисленное значение для адреса памяти вашего компьютера. Это похоже на сравнение целых чисел.
Кемин Чжоу
5
@KeminZhou: это верно на большинстве современных компьютеров, но в целом неверно. Даже на старом ПК 8086 1980 года это было ложно
Старынкевич
109
Немного фактов вот соответствующий текст из спецификаций
Оператор равенства (==,! =)
Указатели на объекты одного типа можно сравнить на предмет равенства с «интуитивно понятными» ожидаемыми результатами:
Из § 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
Также ОК:
structX {int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Но это зависит от somethingвашего вопроса:
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
}
Бонус: что еще есть в стандартной библиотеке?
§ 20.8.5 / 8 : «Для шаблонов greater, less, greater_equalи less_equal, специализации для любого типа указателя дают полный порядок, даже если встроенные операторы <, >, <=, >=этого не делают.»
Итак, вы можете глобально заказывать любые лишние, void*если ими пользуетесь std::less<>и друзья, а не голые operator<.
Сегодня неподражаемый @JerryCoffin сообщил мне о том, что стандартная библиотека имеет более строгие спецификации для шаблонов объектов функций, определенных в <functional>. Добавлен.
Это немного сложнее, если задействовано множественное наследование.
fredoverflow
17
Подводить итоги. Если мы хотим увидеть, указывают ли два указателя на одно и то же место в памяти, мы можем это сделать. Также, если мы хотим сравнить содержимое памяти, на которую указывают два указателя, мы тоже можем это сделать, просто не забудьте сначала разыменовать их.
Если у нас есть
int *a = something;
int *b = something;
которые представляют собой два указателя одного типа, мы можем:
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;
}
Выход:
p1 and p2 alias each other
p3 and p4 donot alias each other
Ответы:
Да, это определение равенства указателей: они оба указывают на одно и то же место (или являются псевдонимами указателя )
источник
Немного фактов вот соответствующий текст из спецификаций
Оператор равенства (==,! =)
Указатели на объекты одного типа можно сравнить на предмет равенства с «интуитивно понятными» ожидаемыми результатами:
Из § 5.10 стандарта C ++ 11:
Операторы отношения (<,>, <=,> =)
Из § 5.9 стандарта C ++ 11:
Итак, если у вас было:
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;
которые представляют собой два указателя одного типа, мы можем:
Сравните адрес памяти:
и сравните содержимое:
источник
Простой код для проверки псевдонима указателя:
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}--------------------------------------------------*/
источник