पॉइंटर्स की तुलना कैसे करें?


88

मान लीजिए कि मेरे पास 2 संकेत हैं:

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

यदि मैं उनकी तुलना करना चाहता हूं और यह देखना चाहता हूं कि क्या वे उसी स्थान पर इंगित करते हैं (== ख) काम करते हैं?


6
IIRC पॉइंटर्स की तुलना अपरिभाषित है, जब तक कि वे एक ही सरणी में तत्वों को इंगित न करें
sehe

1
@ अरे अरे, नीचे आपका जवाब इस पुरानी टिप्पणी को रद्द करता है।
स्पेंसर

जवाबों:


72

हां, यह सूचक समानता की परिभाषा है: वे दोनों एक ही स्थान पर इंगित करते हैं (या सूचक उपनाम हैं )


2
सूचक आपके कंप्यूटर में मेमोरी एड्रेस के लिए अनिवार्य रूप से एक पूर्णांक मान है। यह पूर्णांकों की तुलना करने जैसा है।
केमिन झोउ

6
@KeminZhou: यह वर्तमान कंप्यूटरों पर सही है, लेकिन सामान्य रूप से गलत है। यहां तक ​​कि पुराने 1980 के पीसी एटी 8086 पर यह गलत था
बेसिल स्टारीनेवविच

110

कुछ तथ्यों के लिए यहां विनिर्देशों से संबंधित पाठ है

समानता ऑपरेटर (==; =!)

समान प्रकार की वस्तुओं की तुलना 'सहज' अपेक्षित परिणामों के साथ समानता के लिए की जा सकती है:

से § 5.10 सी ++ 11 मानक की:

समान प्रकार के सूचक (सूचक रूपांतरण के बाद) की तुलना समानता के लिए की जा सकती है। एक ही प्रकार के दो पॉइंटर्स बराबर तुलना करते हैं यदि और केवल यदि वे दोनों शून्य हैं, तो दोनों एक ही फ़ंक्शन को इंगित करते हैं, या दोनों एक ही पते ( 3.9.2 ) का प्रतिनिधित्व करते हैं ।

(सदस्य और शून्य सूचक स्थिरांक को संकेत की तुलना पर विवरण छोड़कर - वे 'डू व्हाट आई मीन' की इसी पंक्ति को जारी रखते हैं :)

  • [...] यदि दोनों ऑपरेंड अशक्त हैं, तो वे समान हैं। अन्यथा यदि केवल एक अशक्त है, तो वे असमान की तुलना करते हैं। [...]

सबसे 'विशिष्ट' कैविएट को आभासी लोगों के साथ क्या करना है, और यह भी उम्मीद करने के लिए तार्किक बात लगती है:

  • [...] यदि या तो एक आभासी सदस्य फ़ंक्शन के लिए एक संकेतक है, तो परिणाम अनिर्दिष्ट है। अन्यथा वे बराबर तुलना करते हैं यदि और केवल तभी वे उसी व्युत्पन्न वस्तु (1.8) के एक ही सदस्य को संदर्भित करेंगे या यदि वे संबंधित श्रेणी के प्रकार के काल्पनिक ऑब्जेक्ट के साथ डीरेफर किए गए थे तो उसी उप-विषय। [...]

संबंधित ऑपरेटर (<,>, <=,> =)

से § 5.9 सी ++ 11 मानक की:

एक ही प्रकार की वस्तुओं या कार्यों को इंगित करने वाले (सूचक रूपांतरण के बाद) की तुलना इस प्रकार की जा सकती है, जिसके परिणाम निम्नानुसार हैं:

  1. दो संकेत पी और एक ही वस्तु या समारोह, या एक ही सरणी के अंत अतीत दोनों बिंदु से एक है, के लिए एक ही प्रकार के बिंदु के क्ष या दोनों अशक्त, तो कर रहे हैं p<=qऔर p>=qदोनों उपज सच और p<qऔर p>qदोनों उपज झूठी।
  2. यदि दो पॉइंटर्स p और q एक ही प्रकार के अलग-अलग ऑब्जेक्ट्स को इंगित करते हैं जो एक ही ऑब्जेक्ट या एक ही एरे के तत्वों या अलग-अलग फ़ंक्शन के सदस्य नहीं हैं , या यदि उनमें से केवल एक ही शून्य है, तो परिणाम p<q, p>q, p<=q,और p>=q अनिर्दिष्ट हैं
  3. यदि दो संकेत एक ही वस्तु के गैर-स्थैतिक डेटा सदस्यों को इंगित करते हैं, या ऐसे सदस्यों के उप-तत्वों या सरणी तत्वों के लिए, पुनरावर्ती रूप से, बाद में घोषित सदस्य के लिए सूचक अधिक से अधिक तुलना प्रदान करता है, बशर्ते दोनों सदस्यों का समान अभिगम नियंत्रण (क्लाज 11) हो। बशर्ते उनका वर्ग कोई संघ न हो।
  4. यदि दो संकेत अलग-अलग अभिगम नियंत्रण (क्लाज 11) के साथ एक ही वस्तु के गैर-स्थैतिक डेटा सदस्यों को इंगित करते हैं, तो परिणाम अनिर्दिष्ट है।
  5. यदि दो संकेत एक ही यूनियन ऑब्जेक्ट के गैर-स्थैतिक डेटा सदस्यों को इंगित करते हैं, तो वे बराबर (रूपांतरण के बाद void*, यदि आवश्यक हो) की तुलना करते हैं। यदि दो संकेत एक ही सरणी के तत्वों को इंगित करते हैं या एक सरणी के अंत से परे हैं, तो सूचक उच्चतर सबस्क्रिप्ट के साथ ऑब्जेक्ट पर उच्चतर होता है।
  6. अन्य सूचक तुलना अनिर्दिष्ट हैं।

तो, यदि आपके पास था:

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<


क्या stackoverflow.com/questions/8412694/address-of-array केint *a = arr; संदर्भ सहित लाइन से लाभ होगा ? मुझे यकीन नहीं है कि अगर यह पूछे गए सवाल के लिए पर्याप्त प्रासंगिक है ...
nonsensickle

आज, inimitable @JerryCoffin ने मुझे इस तथ्य से अवगत कराया कि मानक पुस्तकालय में परिभाषित फ़ंक्शन फ़ंक्शन टेम्पलेट के लिए अधिक कड़े विनिर्देश हैं <functional>। जोड़ा गया।
23

ऐसा लगता है कि चल रहे C ++ ड्राफ्ट में यह अध्याय बदल गया है। जब तक मैं इसे गलत नहीं समझ लेता, कोई अधिक अनिर्दिष्ट व्यवहार नहीं है: open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
SomeWittyUserh


25

==संकेत पर ऑपरेटर ने अंकीय पते की तुलना करेंगे और इसलिए यह निर्धारित अगर वे एक ही वस्तु को इंगित।


12
यदि एक से अधिक विरासत शामिल है तो यह थोड़ा अधिक जटिल है।
fredoverflow

17

सारांश में। अगर हम यह देखना चाहते हैं कि दो पॉइंटर्स एक ही मेमोरी लोकेशन की ओर इशारा करते हैं तो हम ऐसा कर सकते हैं। इसके अलावा, अगर हम दो पॉइंटर्स द्वारा बताई गई मेमोरी की सामग्री की तुलना करना चाहते हैं, तो हम वह भी कर सकते हैं, बस पहले डीरेलमेंट करने के लिए रिमाइबर करें।

अगर हमारे पास है

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

हम एक ही प्रकार के दो संकेत कर सकते हैं:

स्मृति पते की तुलना करें:

a==b

और सामग्री की तुलना करें:

*a==*b

1

सूचक अलियासिंग की जांच करने के लिए सरल कोड:

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

1

बिंदुओं की तुलना पोर्टेबल नहीं है, उदाहरण के लिए डॉस में अलग-अलग पॉइंटर मान एक ही स्थान पर इंगित करते हैं, पॉइंटर्स की तुलना झूठी होती है।

/*--{++: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}--------------------------------------------------*/

बोरलैंड सी 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}--------------------------------------------------*/
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.