İşaretçiler nasıl karşılaştırılır?


88

2 işaretçim olduğunu varsayalım:

int *a = something;
int *b = something;

Onları karşılaştırmak ve aynı yeri gösterip göstermediklerini görmek istersem (a == b) işe yarar mı?


6
Aynı dizideki öğeleri işaret etmedikçe, işaretçileri karşılaştıran IIRC tanımsızdır
sehe

1
@sehe Hey, aşağıdaki cevabınız bu eski yorumu iptal ediyor.
Spencer

Yanıtlar:


72

Evet, işaretçi eşitliğinin tanımı budur: ikisi de aynı konumu gösterir (veya işaretçi takma adlarıdır )


2
İşaretçi (sıradan bir terimle), esasen bilgisayarınızdaki bellek adresi için bir tam sayı değeridir. Tam sayıları karşılaştırmak gibidir.
Kemin Zhou

6
@KeminZhou: Bu mevcut bilgisayarların çoğunda doğrudur, ancak genel olarak yanlıştır. Eski 1980 PC AT
8086'da

110

Biraz bilgi için şartnamelerden ilgili metin burada

Eşitlik operatörü (==,! =)

Aynı türden nesnelere yönelik işaretçiler, 'sezgisel' beklenen sonuçlarla eşitlik açısından karşılaştırılabilir:

Kaynaktan § 5.10 C ++ 11 standardı:

Aynı türden işaretçiler (işaretçi dönüşümlerinden sonra) eşitlik açısından karşılaştırılabilir. Aynı türden iki işaretçi, ancak ve ancak ikisi de boş ise, her ikisi de aynı işlevi gösteriyorsa veya her ikisi de aynı adresi temsil ediyorsa, eşittir ( 3.9.2 ).

(işaretçilerin üye ve / veya boş işaretçi sabitleriyle karşılaştırılmasına ilişkin ayrıntıları dışarıda bırakarak - aynı 'Demek İstediğimi Yap' satırından devam ederler :)

  • [...] Her iki işlenen de null ise, eşit olarak karşılaştırırlar. Aksi takdirde, yalnızca biri boşsa, eşit olmayanları karşılaştırırlar. [...]

En 'göze çarpan' uyarı sanallarla ilgili ve beklenecek mantıksal şey de bu gibi görünüyor:

  • [...] herhangi biri sanal üye işlevine bir göstericiyse, sonuç belirtilmez. Aksi takdirde, ancak ve ancak aynı en çok türetilmiş nesnenin (1.8) aynı üyesine veya ilişkili sınıf türünün varsayımsal bir nesnesiyle başvurulanlarsa aynı alt nesneye başvururlarsa eşit karşılaştırırlar. [...]

İlişkisel operatörler (<,>, <=,> =)

Gönderen § 5.9 C ++ 11 standardı:

Aynı türdeki nesnelere veya işlevlere işaretçiler (işaretçi dönüştürmelerinden sonra), aşağıdaki gibi tanımlanan bir sonuçla karşılaştırılabilir:

  1. Aynı türdeki iki p ve q işaretçisi aynı nesneyi veya işlevi gösteriyorsa veya her ikisi de aynı dizinin sonunu bir geçiyorsa veya her ikisi de boşsa, o zaman p<=qve p>=qher ikisi de doğru p<qve p>qher ikisi de yanlış verir.
  2. Aynı tipteki iki işaretçi p ve q , aynı nesnenin veya aynı dizinin öğeleri veya farklı işlevlerin üyesi olmayan farklı nesnelere işaret ederse veya bunlardan yalnızca biri boşsa, sonuçları belirtilmezp<q, p>q, p<=q, ve p>=q belirtilmez .
  3. İki işaretçi, aynı nesnenin statik olmayan veri üyelerini veya bu tür üyelerin alt nesnelerini veya dizi öğelerini özyinelemeli olarak gösterirse, sonraki bildirilen üyeye işaretçi, iki üyenin aynı erişim kontrolüne sahip olması koşuluyla daha büyük karşılaştırır (Madde 11) ve sınıflarının bir birlik olmaması koşuluyla.
  4. İki işaretçi, aynı nesnenin farklı erişim kontrolüne sahip statik olmayan veri üyelerine işaret ederse (Madde 11), sonuç belirtilmez.
  5. İki işaretçi aynı birleşim nesnesinin statik olmayan veri üyelerine işaret ederse, eşit olarak karşılaştırırlar ( void*gerekirse dönüştürüldükten sonra ). İki işaretçi aynı dizinin öğelerine veya dizinin sonunun ötesindeki öğelere işaret ederse, alt simge daha yüksek olan nesneye işaretçi daha yüksek olanı karşılaştırır.
  6. Diğer işaretçi karşılaştırmaları belirtilmemiştir.

Öyleyse, varsa:

int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined

Ayrıca tamam:

struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined

Ancak somethingsorunuza bağlıdır :

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: Standart kitaplıkta başka neler var?

§ 20.8.5 / 8 : "şablonlarında greater, less, greater_equal, ve less_equal, herhangi bir işaretçi türü için uzmanlık yerleşik operatörler bile, toplam sipariş verim <, >, <=, >=yok."

Yani, kullandığınız ve arkadaş olduğunuz sürece, herhangi bir tuhaf sipariş verebilirsiniz , çıplak değil .void*std::less<>operator<


Misiniz int *a = arr;referans dahil satır fayda stackoverflow.com/questions/8412694/address-of-array ? Yine de sorulan soruyla yeterince alakalı olup olmadığından emin değilim ...
anlamsız

Bugün, benzersiz @JerryCoffin, standart kitaplığın, içinde tanımlanan işlev nesnesi şablonları için daha katı özelliklere sahip olduğu gerçeğinin farkına varmamı sağladı <functional>. Katma.
sehe

Görünüşe göre bu bölüm devam eden C ++ taslağında değişmiş. Yanlış anlamadıysam
SomeWittyUsername


25

==İşaretçileri operatör kendi sayısal adresini karşılaştırın ve aynı nesneye işaret olmadığını dolayısıyla belirleyecektir.


12
Birden fazla kalıtım söz konusuysa durum biraz daha karmaşıktır.
fredoverflow

17

Sonuç olarak. Eğer iki göstericinin aynı hafıza konumuna işaret edip etmediğini görmek istiyorsak, bunu yapabiliriz. Ayrıca iki işaretçi tarafından gösterilen hafızanın içeriğini karşılaştırmak istersek, bunu da yapabiliriz, önce bunlara referans vermeyi unutmayın.

Eğer sahipsek

int *a = something; 
int *b = something;

yapabileceğimiz aynı türden iki işaretçi:

Bellek adresini karşılaştırın:

a==b

ve içeriği karşılaştırın:

*a==*b

1

İşaretçi takma adını kontrol etmek için basit kod:

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;
}

Çıktı:

p1 and p2 alias each other
p3 and p4 do not alias each other

1

İşaretçileri karşılaştırmak taşınabilir değildir, örneğin DOS'ta farklı işaretçi değerleri aynı konumu gösterir, işaretçilerin karşılaştırılması yanlış döndürür.

/*--{++: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 altında derleyin, işte sonuç:

/*--{++: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}--------------------------------------------------*/
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.