2012-07-24 20 views
84

आज जब मैं दूसरों के कोड पढ़ रहा था, मैंने void *func(void* i); जैसे कुछ देखा, यह void* का अर्थ क्रमशः फ़ंक्शन नाम और चर प्रकार के लिए क्या है?शून्य * मतलब और इसका उपयोग कैसे किया जाता है?

इसके अतिरिक्त, हमें इस तरह के सूचक का उपयोग करने और इसे कैसे उपयोग करने की आवश्यकता है?

+2

आप किस सी पुस्तक का उपयोग कर रहे हैं? आप एक पूरे अध्याय के बेहतर हिस्से के लिए पूछ रहे हैं। – cnicutar

+1

http://stackoverflow.com/questions/692564/concept-of-void-pointer-in-c-programming – WDan

+0

पर एक बार देखें: http://stackoverflow.com/questions/1043034/what-does -वोइड-माध्य-इन-सीसी-एंड-सी और यहां: http://stackoverflow.com/questions/7324860/using-void-in-c – d33pika

उत्तर

110

void पर एक सूचक "जेनेरिक" सूचक प्रकार है। एक void * किसी भी अन्य सूचक प्रकार में एक स्पष्ट कलाकार के बिना परिवर्तित किया जा सकता है। आप void * को अस्वीकार नहीं कर सकते हैं या इसके साथ पॉइंटर अंकगणित नहीं कर सकते हैं; आपको इसे एक पॉइंटर में पहले एक पूर्ण डेटा प्रकार में परिवर्तित करना होगा।

यह उन स्थानों पर उपयोग किया जाता है जहां आपको एक ही कोड में विभिन्न सूचक प्रकारों के साथ काम करने में सक्षम होना चाहिए। एक आमतौर पर उद्धृत उदाहरण लाइब्रेरी समारोह qsort है:

void qsort(void *base, size_t nmemb, size_t size, 
      int (*compar)(const void *, const void *)); 

base एक सरणी का पता है, nmemb सरणी में तत्वों की संख्या है, size प्रत्येक तत्व का आकार है, और compar एक करने के लिए एक सूचक है फ़ंक्शन जो सरणी के दो तत्वों की तुलना करता है।यह बहुत की तरह कहा जाता हो जाता है:

int iArr[10]; 
double dArr[30]; 
long lArr[50]; 
... 
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt); 
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble); 
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong); 

सरणी भाव iArr, dArr, और lArr परोक्ष समारोह कॉल में प्रकार सूचक को सरणी प्रकार से बदल रहे हैं, और प्रत्येक परोक्ष int/double/long करने के लिए "सूचक से बदल जाती है "टू पॉइंटर टू void"।

तुलना कार्यों कुछ ऐसा दिखाई देगा:

int compareInt(const void *lhs, const void *rhs) 
{ 
    const int *x = lhs; // convert void * to int * by assignment 
    const int *y = rhs; 

    if (*x > *y) return 1; 
    if (*x == *y) return 0; 
    return -1; 
} 

void *, qsort को स्वीकार करने में किसी भी प्रकार की सरणियों के साथ काम कर सकते हैं के द्वारा।

void * का उपयोग करने का नुकसान यह है कि आप खिड़की से बाहर आने वाले यातायात में सुरक्षा को फेंक देते हैं। वहाँ गलत तुलना दिनचर्या का उपयोग कर से बचाने के लिए कुछ भी नहीं है:

qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt); 

compareInt अपने तर्कों int रों की ओर इशारा करते जा करने के लिए उम्मीद कर रही है, लेकिन वास्तव में double के साथ काम कर रहा है। संकलन समय पर इस समस्या को पकड़ने का कोई तरीका नहीं है; आप बस एक गलत प्रकार की सरणी के साथ हवादार हो जाएगा।

+3

यह वास्तव में गारंटी नहीं है कि एक 'शून्य *' को फ़ंक्शन पॉइंटर पर डाला जा सकता है। लेकिन डेटा पॉइंटर्स के लिए जो आपने कहा है। – Vatine

2
void* 

'कोई अनुमान नहीं है कि स्मृति किस प्रकार संग्रहित है' स्मृति के लिए सूचक है। उदाहरण के लिए, यदि आप फ़ंक्शन के लिए तर्क पारित करना चाहते हैं, तो आप इसका उपयोग कर सकते हैं और यह तर्क कई प्रकार के हो सकता है और फ़ंक्शन में आप प्रत्येक प्रकार को संभाल लेंगे।

-5

फ़ंक्शन नाम से पहले VOID का अर्थ है कि यह कुछ भी वापस नहीं करता है। बस कुछ सामान कर रहा हूँ। दूसरी ओर पैरामीटर के रूप में VOID इसे सामान्य कार्य बनाता है जो किसी भी प्रकार के पैरामीटर को स्वीकार कर सकता है। लेकिन आपको इस पैरामीटर के आकार के साथ फ़ंक्शन प्रदान करना होगा।

+2

'शून्य' और 'शून्य *' के बीच एक अंतर है। अन्य उत्तरों देखें – Aftnix

0

फ़ंक्शन एक मनमाना प्रकार के लिए एक सूचक लेता है और ऐसा एक देता है।

2

आप इस आलेख को पॉइंटर्स http://www.cplusplus.com/doc/tutorial/pointers/ के बारे में देख सकते हैं और अध्याय पढ़ सकते हैं: शून्य पॉइंटर्स

यह सी भाषा के लिए भी काम करता है।

पॉइंटर का शून्य प्रकार एक विशेष प्रकार का सूचक है। सी ++ में, शून्य प्रकार की अनुपस्थिति का प्रतिनिधित्व करता है, इसलिए शून्य पॉइंटर्स पॉइंटर्स हैं जो किसी ऐसे मान पर इंगित करते हैं जिसमें कोई प्रकार नहीं है (और इस प्रकार एक अनिश्चित लंबाई और अनिश्चित अव्यवस्था गुण)।

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

17

शून्य का उपयोग करना * का अर्थ है कि फ़ंक्शन एक पॉइंटर ले सकता है जिसे एक विशिष्ट प्रकार की आवश्यकता नहीं होती है। उदाहरण के लिए, सॉकेट कार्यों में, आप

send(void * pData, int nLength) 

है इसका मतलब है आप

char * data = "blah"; 
send(data, strlen(data)); 

POINT p; 
p.x = 1; 
p.y = 2; 
send(&p, sizeof(POINT)); 
+0

तो यह अन्य भाषाओं में जेनेरिक की तरह काफी है, लेकिन बिना किसी प्रकार की जांच के, है ना? –

+3

मुझे लगता है कि यह समान होगा, हालांकि कोई प्रकार की जांच नहीं है, इसलिए कोई गलती करने से बहुत अजीब परिणाम हो सकते हैं या प्रोग्राम को क्रैश हो सकता है। – TheSteve

1

एक void* एक सूचक है, कई मायनों में यह कॉल कर सकते हैं, उदाहरण के लिए, लेकिन क्या यह के लिए अंक के प्रकार अनिर्दिष्ट है जब आप किसी फ़ंक्शन में शून्य पॉइंटर पास करते हैं तो आपको यह जानने की आवश्यकता होगी कि इसका उपयोग करने के लिए फ़ंक्शन में बाद में उस सही प्रकार पर वापस डालने के लिए इसका प्रकार क्या था। आपको pthreads में उदाहरण दिखाई देंगे जो आपके उदाहरण में प्रोटोटाइप के साथ फ़ंक्शंस का उपयोग करते हैं जो थ्रेड फ़ंक्शन के रूप में उपयोग किए जाते हैं। इसके बाद आप void* तर्क को अपने चयन के सामान्य डेटाटाइप पर पॉइंटर के रूप में उपयोग कर सकते हैं और फिर इसे अपने थ्रेड फ़ंक्शन के भीतर उपयोग करने के लिए उस प्रकार पर वापस डालें। शून्य पॉइंटर्स का उपयोग करते समय आपको सावधान रहना होगा, भले ही आप अपने वास्तविक प्रकार के सूचक के मामले में वापस न आएं, आप सभी प्रकार की समस्याओं के साथ समाप्त हो सकते हैं।

1

C11 मानक (n1570) §6.2.2.3 AL1 P55 का कहना है:

void करने के लिए एक सूचक किसी भी वस्तु प्रकार के करने के लिए या एक सूचक से परिवर्तित किया जा सकता है। किसी ऑब्जेक्ट प्रकार के लिए पॉइंटर को पॉइंटर में शून्य में बदल दिया जा सकता है; परिणाम मूल सूचक के बराबर की तुलना करेगा।

आप किसी ऑब्जेक्ट प्रकार के सूचक के स्टोर करने के लिए यह सामान्य सूचक का उपयोग कर सकते हैं, लेकिन आप इसके साथ हमेशा की तरह अंकगणितीय आपरेशनों उपयोग नहीं कर सकते और आप इसे सम्मान नहीं कर सकते।

2

सी इस संबंध में उल्लेखनीय है प्राप्त करने के लिए इस लिंक का उपयोग कर सकते हैं। कोई भी कह सकता है शून्य शून्यता शून्य * सब कुछ है (हर चीज हो सकता है)

यह सिर्फ इतना छोटा * है जो अंतर बनाता है।

रीन ने इसे इंगित किया है। एक शून्य * कुछ स्थान के लिए एक सूचक है। उपयोगकर्ता को "व्याख्या" करने का तरीका क्या है।

सी में अपारदर्शी प्रकार रखने का यही एकमात्र तरीका है। ग्लिब या सामान्य डेटा संरचना पुस्तकालयों में बहुत प्रमुख उदाहरण पाए जा सकते हैं। इसका उल्लेख "सी इंटरफेस और कार्यान्वयन" में बहुत विस्तृत है।

मेरा सुझाव है कि आप पूरा अध्याय पढ़ें और "इसे प्राप्त करने" के लिए एक सूचक की अवधारणा को समझने का प्रयास करें।

2

एक शून्य सूचक जेनेरिक सूचक के रूप में जाना जाता है। मैं एक नमूना pthread परिदृश्य के साथ समझाऊंगा।

धागा समारोह pthread एपीआई डिजाइनरों तर्क माना जाता है और धागा समारोह के मान के रूप में

void *(*start_routine)(void*) 

प्रोटोटाइप होगा। यदि उन चीजों को सामान्य बना दिया जाता है, तो हम तर्क के रूप में भेजते समय * शून्य को कास्ट टाइप कर सकते हैं। इसी तरह वापसी मूल्य शून्य से पुनर्प्राप्त किया जा सकता है * (लेकिन मैंने थ्रेड फ़ंक्शन से कभी भी वापसी मानों का उपयोग नहीं किया)।

void *PrintHello(void *threadid) 
{ 
    long tid; 

    // ***Arg sent in main is retrieved *** 
    tid = (long)threadid; 
    printf("Hello World! It's me, thread #%ld!\n", tid); 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) 
{ 
    pthread_t threads[NUM_THREADS]; 
    int rc; 
    long t; 
    for(t=0; t<NUM_THREADS; t++){ 
     //*** t will be type cast to void* and send as argument. 
     rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t); 
     if (rc){ 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     exit(-1); 
     } 
    }  
    /* Last thing that main() should do */ 
    pthread_exit(NULL); 
} 
संबंधित मुद्दे