Pointer (dalam istilah awam) pada dasarnya adalah nilai integer untuk alamat memori di komputer Anda. Ini seperti membandingkan bilangan bulat.
Kemin Zhou
6
@KeminZhou: ini benar di sebagian besar komputer saat ini, tetapi salah secara umum. Bahkan pada PC 1980 yang lama AT 8086 itu palsu
Basile Starynkevitch
110
Untuk sedikit fakta berikut ini adalah teks yang relevan dari spesifikasinya
Operator persamaan (==,! =)
Pointer ke objek dengan tipe yang sama dapat dibandingkan untuk persamaan dengan hasil yang diharapkan 'intuitif':
Dari § 5.10 standar C ++ 11:
Pointer dengan tipe yang sama (setelah konversi pointer) dapat dibandingkan untuk persamaan. Dua pointer berjenis sama dibandingkan jika dan hanya jika keduanya nol, keduanya mengarah ke fungsi yang sama, atau keduanya mewakili alamat yang sama ( 3.9.2 ).
(meninggalkan detail tentang perbandingan pointer ke anggota dan atau konstanta pointer nol - mereka melanjutkan ke baris yang sama dari 'Do What I Mean' :)
[...] Jika kedua operan bernilai nol, keduanya sama. Sebaliknya jika hanya satu yang nol, mereka membandingkan tidak sama. [...]
Peringatan yang paling 'mencolok' berkaitan dengan dunia maya, dan tampaknya juga logis untuk diharapkan:
[...] jika salah satu penunjuk ke fungsi anggota virtual, hasilnya tidak ditentukan. Jika tidak, mereka membandingkan sama jika dan hanya jika mereka merujuk ke anggota yang sama dari objek yang paling banyak diturunkan (1.8) atau subobjek yang sama jika mereka dirujuk dengan objek hipotetis dari tipe kelas terkait. [...]
Operator relasional (<,>, <=,> =)
Dari § 5.9 standar C ++ 11:
Pointer ke objek atau fungsi dengan tipe yang sama (setelah konversi pointer) dapat dibandingkan, dengan hasil yang ditentukan sebagai berikut:
Jika dua pointer p dan q dari titik tipe yang sama ke objek yang sama atau fungsi, atau keduanya satu titik melewati akhir array yang sama, atau keduanya nol, maka p<=qdan p>=qbaik hasil yang benar dan p<qdanp>q kedua hasil palsu.
Jika dua penunjuk p dan q berjenis sama mengarah ke objek berbeda yang bukan anggota objek atau elemen yang sama dari larik yang sama atau ke fungsi yang berbeda, atau jika hanya satu di antaranya yang null, hasil dari p<q,p>q,p<=q,dan
p>=qtidak ditentukan .
Jika dua penunjuk menunjuk ke anggota data non-statis dari objek yang sama, atau ke subobjek atau elemen larik dari anggota tersebut, secara rekursif, penunjuk ke anggota yang dideklarasikan nanti akan lebih besar asalkan kedua anggota memiliki kontrol akses yang sama (Klausul 11) dan asalkan kelas mereka bukan serikat pekerja.
Jika dua pointer menunjuk ke anggota data non-statis dari objek yang sama dengan kontrol akses berbeda (Klausul 11) hasilnya tidak ditentukan.
Jika dua pointer menunjuk ke anggota data non-statis dari objek gabungan yang sama, keduanya akan dibandingkan sama (setelah konversi ke void* , jika perlu). Jika dua penunjuk menunjuk ke elemen dari larik yang sama atau satu di luar akhir larik, penunjuk ke objek dengan subskrip yang lebih tinggi membandingkan lebih tinggi.
Perbandingan penunjuk lainnya tidak ditentukan.
Jadi, jika Anda memiliki:
int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined
Juga Oke:
structX {int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined
Tetapi itu tergantung pada somethingpertanyaan Anda:
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: apa lagi yang ada di perpustakaan standar?
§ 20.8.5 / 8 : "Untuk template greater, less, greater_equal, dan less_equal, spesialisasi untuk setiap jenis pointer menghasilkan total order, bahkan jika built-in operator <, >, <=,>= tidak."
Jadi, Anda dapat memesan ganjil secara global void*selama Anda menggunakan std::less<>dan teman, tidak telanjang operator<.
Hari ini, @JerryCoffin yang tak ada bandingannya membuat saya sadar akan fakta bahwa pustaka standar memiliki spesifikasi yang lebih ketat untuk templat objek fungsi yang didefinisikan di <functional>. Ditambahkan.
Ini sedikit lebih rumit jika melibatkan banyak warisan.
fredoverflow
17
Untuk menyimpulkan. Jika kita ingin melihat apakah dua penunjuk menunjuk ke lokasi memori yang sama kita bisa melakukannya. Juga jika kita ingin membandingkan isi memori yang ditunjukkan oleh dua petunjuk kita bisa melakukannya juga, ingat saja untuk membedakannya terlebih dahulu.
Jika kita punya
int *a = something;
int *b = something;
yang merupakan dua penunjuk dari jenis yang sama yang kami dapat:
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;
}
Keluaran:
p1 and p2 alias each other
p3 and p4 donot alias each other
Jawaban:
Ya, itulah definisi persamaan pointer: keduanya menunjuk ke lokasi yang sama (atau alias pointer )
sumber
Untuk sedikit fakta berikut ini adalah teks yang relevan dari spesifikasinya
Operator persamaan (==,! =)
Pointer ke objek dengan tipe yang sama dapat dibandingkan untuk persamaan dengan hasil yang diharapkan 'intuitif':
Dari § 5.10 standar C ++ 11:
Operator relasional (<,>, <=,> =)
Dari § 5.9 standar C ++ 11:
Jadi, jika Anda memiliki:
int arr[3]; int *a = arr; int *b = a + 1; assert(a != b); // OK! well defined
Juga Oke:
struct X { int x,y; } s; int *a = &s.x; int *b = &s.y; assert(b > a); // OK! well defined
Tetapi itu tergantung pada
something
pertanyaan Anda: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: apa lagi yang ada di perpustakaan standar?
§ 20.8.5 / 8 : "Untuk template
greater
,less
,greater_equal
, danless_equal
, spesialisasi untuk setiap jenis pointer menghasilkan total order, bahkan jika built-in operator<
,>
,<=
,>=
tidak."Jadi, Anda dapat memesan ganjil secara global
void*
selama Anda menggunakanstd::less<>
dan teman, tidak telanjangoperator<
.sumber
int *a = arr;
garis mendapat manfaat dari menyertakan referensi ke stackoverflow.com/questions/8412694/address-of-array ? Saya tidak yakin apakah itu cukup relevan dengan pertanyaan yang diajukan ...<functional>
. Ditambahkan.The
==
operator pada pointer akan membandingkan alamat numerik mereka dan karenanya menentukan apakah mereka menunjuk ke objek yang sama.sumber
Untuk menyimpulkan. Jika kita ingin melihat apakah dua penunjuk menunjuk ke lokasi memori yang sama kita bisa melakukannya. Juga jika kita ingin membandingkan isi memori yang ditunjukkan oleh dua petunjuk kita bisa melakukannya juga, ingat saja untuk membedakannya terlebih dahulu.
Jika kita punya
int *a = something; int *b = something;
yang merupakan dua penunjuk dari jenis yang sama yang kami dapat:
Bandingkan alamat memori:
dan bandingkan isinya:
sumber
Kode sederhana untuk memeriksa penunjuk aliasing:
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; }
Keluaran:
p1 and p2 alias each other p3 and p4 do not alias each other
sumber
Membandingkan pointer tidak portabel, misalnya di DOS poin nilai pointer yang berbeda ke lokasi yang sama, perbandingan pointer mengembalikan 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}--------------------------------------------------*/
Kompilasi di bawah Borland C 5.0, inilah hasilnya:
/*--{++: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}--------------------------------------------------*/
sumber