जवाबों:
सबसे सरल उत्तर, यह मानते हुए कि आप विभिन्न प्लेटफार्मों के बीच प्रारूप में योनि और भिन्नताओं को ध्यान में नहीं रखते हैं, मानक %p
अंकन है।
C99 मानक (ISO / IEC 9899: 1999) §7.19.6.1 ¶8 में कहता है:
p
तर्क एक संकेतक होगाvoid
। सूचक का मान कार्यान्वयन-परिभाषित तरीके से, मुद्रण वर्णों के अनुक्रम में परिवर्तित हो जाता है।
(सी 11 में - आईएसओ / आईईसी 9899: 2011 - जानकारी .27.21.6.1 ¶8 में है।)
कुछ प्लेटफार्मों पर, इसमें एक अग्रणी 0x
और अन्य शामिल होंगे जो यह नहीं करेंगे, और पत्र निचले मामले या ऊपरी-मामले में हो सकते हैं, और सी मानक यह भी परिभाषित नहीं करता है कि यह हेक्साडेसिमल आउटपुट होगा हालांकि मुझे पता है कोई कार्यान्वयन जहां यह नहीं है।
यह बहस करने के लिए कुछ हद तक खुला है कि क्या आपको स्पष्ट रूप से एक (void *)
डाली के साथ बिंदुओं को बदलना चाहिए । यह स्पष्ट हो रहा है, जो आमतौर पर अच्छा होता है (इसलिए यह वही है जो मैं करता हूं), और मानक कहता है 'तर्क एक संकेतक होगा void
'। अधिकांश मशीनों पर, आप एक स्पष्ट डाली को छोड़ कर चले जाते हैं। हालाँकि, यह एक ऐसी मशीन पर बात करेगा जहाँ char *
किसी दिए गए मेमोरी लोकेशन के लिए एक एड्रेस का बिट प्रतिनिधित्व समान मेमोरी लोकेशन के लिए ' कुछ और पॉइंटर ' एड्रेस से अलग हो । यह बाइट-एड्रेस, मशीन के बजाय एक शब्द-संबोधित होगा। इन दिनों ऐसी मशीनें आम नहीं हैं (शायद उपलब्ध नहीं हैं), लेकिन विश्वविद्यालय के बाद मैंने जो पहली मशीन पर काम किया, वह ऐसी थी (ICL Perq)।
यदि आप कार्यान्वयन-परिभाषित व्यवहार से खुश नहीं हैं %p
, तो C99 का उपयोग करें <inttypes.h>
और uintptr_t
इसके बजाय:
printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);
यह आपको अपने आप को सूट करने के लिए प्रतिनिधित्व को ठीक करने की अनुमति देता है। मैंने ऊपरी-मामले में हेक्स अंकों का चयन किया ताकि संख्या समान रूप से समान हो और 0xA1B2CDEF
इस तरह से शुरू में विशेषता डुबकी इस प्रकार दिखाई दे, जैसे 0xa1b2cdef
कि संख्या के साथ ऊपर और नीचे भी न हो। आपकी पसंद हालांकि, बहुत व्यापक सीमाओं के भीतर। (uintptr_t)
कलाकारों स्पष्ट जीसीसी द्वारा की सिफारिश की है, जब यह संकलन समय पर प्रारूप स्ट्रिंग पढ़ सकते हैं। मुझे लगता है कि कलाकारों का अनुरोध करना सही है, हालांकि मुझे यकीन है कि कुछ ऐसे हैं जो चेतावनी को नजरअंदाज करेंगे और अधिकांश समय इसके साथ दूर रहेंगे।
केरेक टिप्पणी में पूछता है:
मैं मानक प्रचार और भिन्न तर्क के बारे में थोड़ा भ्रमित हूं। क्या सभी बिंदुओं को मानक * शून्य करने के लिए बढ़ावा मिलता है? अन्यथा, अगर
int*
, दो बाइट्स, औरvoid*
4 बाइट्स थे, तो यह स्पष्ट रूप से तर्क से चार बाइट्स पढ़ने के लिए एक त्रुटि होगी, गैर?
मैं भ्रम है कि सी मानक कहना है कि सभी वस्तु संकेत दिए गए एक ही आकार है, तो होना चाहिए के तहत किया गया void *
और int *
विभिन्न आकारों नहीं हो सकता। हालाँकि, मुझे क्या लगता है कि C99 मानक का प्रासंगिक खंड इतना सशक्त नहीं है (हालांकि मुझे एक कार्यान्वयन के बारे में नहीं पता है कि मैंने जो सुझाया है वह वास्तव में गलत है):
§6.2.5 प्रकार
¶26 शून्य करने के लिए एक सूचक में एक चरित्र प्रकार के लिए एक संकेतक के रूप में एक ही प्रतिनिधित्व और संरेखण आवश्यकताएं होंगी। 39) इसी प्रकार, संगत प्रकारों के योग्य या अयोग्य संस्करणों की ओर संकेत करने वालों के लिए समान प्रतिनिधित्व और संरेखण आवश्यकताएं होंगी। संरचना के प्रकारों के सभी संकेत एक-दूसरे के समान प्रतिनिधित्व और संरेखण आवश्यकताओं होंगे। यूनियन प्रकार के सभी संकेत एक दूसरे के समान प्रतिनिधित्व और संरेखण आवश्यकताओं होंगे। अन्य प्रकार के पॉइंटर्स के लिए समान प्रतिनिधित्व या संरेखण आवश्यकताओं की आवश्यकता नहीं है।
39) समान प्रतिनिधित्व और संरेखण आवश्यकताओं का तात्पर्य है कि कार्य के लिए तर्क, कार्यों से वापसी के मूल्यों और यूनियनों के सदस्यों के रूप में विनिमयशीलता का अर्थ है।
(C11 अनुभाग 116.2.5, and28, और फुटनोट 48 में बिल्कुल वैसा ही कहता है।)
इसलिए, संरचनाओं के सभी संकेत एक-दूसरे के समान आकार के होने चाहिए, और समान संरेखण आवश्यकताओं को साझा करना चाहिए, भले ही संरचनाएँ बिंदु पर अलग-अलग संरेखण आवश्यकताओं हो। इसी तरह यूनियनों के लिए। चरित्र सूचक और शून्य बिंदु समान आकार और संरेखण आवश्यकताएँ होनी चाहिए। में बदलाव की ओर इशारा int
(अर्थ unsigned int
और signed int
) एक दूसरे के रूप में एक ही आकार और संरेखण आवश्यकताओं होनी चाहिए; अन्य प्रकारों के लिए भी। लेकिन सी मानक औपचारिक रूप से ऐसा नहीं कहता है sizeof(int *) == sizeof(void *)
। ओह ठीक है, एसओ आपको अपनी मान्यताओं का निरीक्षण करने के लिए अच्छा है।
C मानक निश्चित रूप से फ़ंक्शन पॉइंटर्स को ऑब्जेक्ट पॉइंटर्स के समान आकार की आवश्यकता नहीं है। यह आवश्यक था कि डॉस जैसी प्रणालियों पर विभिन्न मेमोरी मॉडल को न तोड़ा जाए। वहां आपके पास 16-बिट डेटा पॉइंटर्स, लेकिन 32-बिट फ़ंक्शन पॉइंटर्स या इसके विपरीत हो सकते हैं। यही कारण है कि सी मानक यह आदेश नहीं देता है कि फ़ंक्शन पॉइंटर्स को ऑब्जेक्ट पॉइंटर्स में बदला जा सकता है और इसके विपरीत।
सौभाग्य से (POSIX को लक्षित करने वाले प्रोग्रामर के लिए), POSIX उल्लंघन में कदम रखता है और यह बताता है कि फ़ंक्शन पॉइंटर्स और डेटा पॉइंटर्स समान आकार हैं:
§2.12.3 सूचक प्रकार
सभी फ़ंक्शन पॉइंटर प्रकारों में शून्य के प्रकार पॉइंटर के समान प्रतिनिधित्व होगा। फ़ंक्शन पॉइंटर का रूपांतरण
void *
प्रतिनिधित्व में परिवर्तन नहीं करेगा। इसvoid *
तरह के रूपांतरण से उत्पन्न एक मूल्य को मूल फ़ंक्शन पॉइंटर प्रकार में परिवर्तित किया जा सकता है, एक स्पष्ट कलाकारों का उपयोग करके, बिना जानकारी के नुकसान के।नोट: ISO C मानक को इसकी आवश्यकता नहीं है, लेकिन यह POSIX अनुरूपता के लिए आवश्यक है।
इसलिए, ऐसा प्रतीत होता है कि स्पष्ट void *
जातियों को कोड में अधिकतम विश्वसनीयता के लिए दृढ़ता से सलाह दी जाती है जब एक सूचक को एक वैरेडिक फ़ंक्शन जैसे कि पास किया जाता है printf()
। POSIX प्रणालियों पर, मुद्रण के लिए एक शून्य सूचक के लिए फ़ंक्शन पॉइंटर डालना सुरक्षित है। अन्य प्रणालियों पर, ऐसा करने के लिए आवश्यक रूप से सुरक्षित नहीं है, और न ही यह आवश्यक है कि void *
बिना कलाकारों के अलावा अन्य बिंदुओं को पारित करना सुरक्षित हो ।
dlsym()
इसके बजाय फ़ंक्शन की अधिकांश आवश्यकताओं को स्थानांतरित कर रहा है । एक दिन मैं बदलाव लिखूंगा ... लेकिन 'एक दिन' आज 'नहीं' है।
void *
को सूचना के नुकसान के बिना a और back में परिवर्तित किया जा सकता है । व्यावहारिक रूप से, बहुत कम मशीनें हैं जहां फ़ंक्शन पॉइंटर का आकार ऑब्जेक्ट पॉइंटर के आकार के समान नहीं है। मुझे नहीं लगता कि मानक मशीनों पर एक फ़ंक्शन पॉइंटर को प्रिंट करने की एक विधि प्रदान करता है जहां था रूपांतरण समस्याग्रस्त है।
p
पॉइंटर्स प्रिंट करने के लिए रूपांतरण विनिर्देशक है। इसे इस्तेमाल करो।
int a = 42;
printf("%p\n", (void *) &a);
याद रखें कि कलाकारों को छोड़ देना अपरिभाषित व्यवहार है और p
रूपांतरण निर्दिष्ट के साथ मुद्रण कार्यान्वयन-परिभाषित तरीके से किया जाता है।
%p
"पॉइंटर" के लिए उपयोग करें , और कुछ और का उपयोग न करें *। आपको उस मानक की गारंटी नहीं है जो आपको किसी विशेष प्रकार के पूर्णांक की तरह एक पॉइंटर का इलाज करने की अनुमति देता है, इसलिए आपको वास्तव में अभिन्न स्वरूपों के साथ अपरिभाषित व्यवहार मिलेगा। (उदाहरण के लिए, %u
एक की उम्मीद है unsigned int
, लेकिन क्या होगा अगर void*
एक अलग आकार या संरेखण की आवश्यकता है unsigned int
?)
*) [देखें जोनाथन का ठीक जवाब!] वैकल्पिक रूप से %p
, आप C99 में जोड़े गए सूचक-विशिष्ट मैक्रो का उपयोग कर सकते हैं <inttypes.h>
।
सभी ऑब्जेक्ट पॉइंटर्स void*
C में निहित रूप से परिवर्तनीय हैं , लेकिन पॉइंटर को एक वैरिएड तर्क के रूप में पास करने के लिए, आपको इसे स्पष्ट रूप से डालना होगा (चूंकि मनमाना ऑब्जेक्ट पॉइंटर्स केवल परिवर्तनीय हैं , लेकिन शून्य पॉइंटर्स के समान नहीं हैं :
printf("x lives at %p.\n", (void*)&x);
void *
(हालांकि printf()
आपके लिए तकनीकी रूप से स्पष्ट कलाकारों की आवश्यकता है, क्योंकि यह एक चर समारोह है)। फ़ंक्शन पॉइंटर्स आवश्यक रूप से परिवर्तनीय नहीं हैं void *
।
void *
को बिना नुकसान के फ़ंक्शन पॉइंटर के लिए और वापस कन्वर्ट करने योग्य होना चाहिए ; सौभाग्य से, हालांकि, POSIX को स्पष्ट रूप से इसकी आवश्यकता है (यह देखते हुए कि यह मानक C का हिस्सा नहीं है)। तो, व्यवहार में, आप इसके साथ भाग सकते हैं (परिवर्तित void (*function)(void)
करना void *
और वापस करना void (*function)(void)
), लेकिन कड़ाई से यह सी मानक द्वारा अनिवार्य नहीं है।
%u
!
%u
और सभी मशीनों%lu
पर गलत हैं , कुछ मशीनों पर नहीं। का विनिर्देश बहुत स्पष्ट है कि जब टाइप किया गया प्रारूप प्रारूप के लिए आवश्यक प्रकार से मेल नहीं खाता है, तो व्यवहार अपरिभाषित है। क्या प्रकार के आकार मेल खाते हैं (जो मशीन के आधार पर सही या गलत हो सकते हैं) अप्रासंगिक है; यह ऐसे प्रकार हैं जिनका मिलान होना चाहिए, और वे कभी नहीं होंगे। printf
अन्य (बहुत अच्छे) उत्तरों के विकल्प के रूप में, आप ( uintptr_t
या / से ) कास्ट कर सकते हैं और संबंधित पूर्णांक रूपांतरण विनिर्देशक का उपयोग कर सकते हैं। यह सूचक को स्वरूपित करने के तरीके में अधिक लचीलापन देता है, लेकिन इन टंकणों को प्रदान करने के लिए सख्ती से कार्यान्वयन की आवश्यकता नहीं है।intptr_t
stdint.h
inttypes.h
#include <stdio.h> int main(void) { int p=9; int* m=&s; printf("%u",m); }
कि %u
क्या प्रारूप विनिर्देशक का उपयोग करके चर का पता प्रिंट करना अपरिभाषित व्यवहार है ? अधिकांश मामलों में परिवर्तनशील का पता सकारात्मक है तो क्या मैं %u
इसके बजाय उपयोग कर सकता हूं %p
?
%u
लिए एक प्रारूप है unsigned int
और इसका उपयोग पॉइंटर तर्क के साथ नहीं किया जा सकता है printf
।
आप उपयोग कर सकते हैं %x
या %X
या %p
; वे सभी सही हैं।
%x
, तो पता निम्न के रूप में दिया जाता है, उदाहरण के लिए:a3bfbc4
%X
, तो पते को अपरकेस के रूप में दिया जाता है, उदाहरण के लिए:A3BFBC4
ये दोनों सही हैं।
यदि आप पते के लिए छह पदों का उपयोग करते हैं %x
या %X
विचार कर रहे हैं, और यदि आप इसका उपयोग %p
करते हैं तो पते के लिए आठ पदों पर विचार कर रहे हैं। उदाहरण के लिए:
void*
? अन्यथा, अगरint*
, दो बाइट्स, औरvoid*
4 बाइट्स थे, तो यह स्पष्ट रूप से तर्क से चार बाइट्स पढ़ने के लिए एक त्रुटि होगी, गैर?