2014-09-04 16 views
7

मैं सी में निम्न सिंटैक्स में परेशानी आ रही:समारोह है कि एक समारोह सूचक वाक्य रचना देता

float (*func(unsigned id))(float value) { 
    ... 
} 

मैं समझता हूँ कि:

  • यह एक समारोह कहा जाता है की एक परिभाषा है func
  • func प्रकार unsignedid
  • func रिटर्न कहा जाता है में से एक तर्क स्वीकार करता है float f(float value)

लेकिन मुझे समझ नहीं आता क्यों f (लौटे समारोह सूचक) के रिटर्न मान अपने तर्क सूची से अलग कर दिया जाता है: एक समारोह ऐसा दिखता है जैसे करने के लिए एक सूचक।

इसके अलावा, func(unsigned id) एक अभिव्यक्ति है जो कुछ सूचक का मूल्यांकन करती है? क्या यही कारण है कि (*func(unsigned id)) काम करता है?

क्या कोई इस वाक्यविन्यास चरण को चरणबद्ध कर सकता है?

+0

एक जवाब के रूप में जोड़ने के लायक नहीं है, लेकिन 'cdecl' एक कमांड लाइन उपकरण है जो आप के लिए यह समझा जाएगा है । – abligh

उत्तर

7

अभिव्यक्ति func(id) एक फ़ंक्शन को एक पॉइंटर देता है जो एक फ्लोट को तर्क के रूप में लेता है और एक फ्लोट देता है।

float(*f)(float v); // pointer to a function 
float val;  

f = func(3);  // returns a pointer to a function 
val = (*f)(3.14); // calls the function pointed to with argument 3.14 
बेशक

, आप पिछले बयान को फिर से लिखने सकता है:

val = (*func(3))(3.14); // take the ptr returned by func(3) and call the function pointed to. 

आप की तरह एक समारोह है, तो:

float fct1 (float v) { return 2.0f*v+3.1f; } 

आप लिख सकते हैं:

f = fct1;  // reassign the pointer to function f to the adress of fct1 

लेट्स वाक्यविन्यास को देखो। सी 11 मानक (मसौदा एन 1570) 6.5.2.2 बिंदु 1 में बताता है: "अभिव्यक्ति जो फ़ंक्शन को इंगित करता है) में" "और बिंदु 3 में कार्य करने के लिए टाइप पॉइंटर होगा: " एक पोस्टफिक्स अभिव्यक्ति कोष्ठक के बाद() अभिव्यक्तियों की संभावित रूप से खाली, अल्पविराम से अलग सूची वाली एक फ़ंक्शन कॉल है। "

यह सामान्य मामलों निश्चित रूप से शामिल किया गया है:

val = fct1 (3.14); // fct1 is the function designator which adresses the function 
val = (*f) (3.14); // (*f) the dereferenced function pointer, so it addresses the function 

लेकिन निम्न मानक के अनुसार भी मान्य है:

val = f(3.14); // This works as well, because f is a pointer to a function 
val = func(3)(3.14) // works also because func(3) is a pointer to a function 

हालांकि पहली अभिव्यक्ति मानव पाठक के लिए अस्पष्ट है, जो सोच सकते हैं फंक्शन डिज़ाइनर के रूप में एफ की, इसे कहीं परिभाषित करने की उम्मीद है। और दूसरा असामान्य भी है। इसके अलावा, सी के पुराने संस्करणों ने उन्हें पहचान नहीं लिया था। 1 9 78 के लिए मेरे के & आर संस्करण को फ़ंक्शन पॉइंटर को कॉल करने के लिए फॉर्म (* f)() की आवश्यकता होती है।

एक अंतिम वाक्य रचनात्मक टिप्पणी: यदि आप float *f (float); के रूप में एफ को परिभाषित करेंगे तो इसे किसी फ़ंक्शन के सूचक के रूप में नहीं समझा जाएगा, लेकिन एक सादा फ़ंक्शन की अगली घोषणा के रूप में जिसे एफ कहा जाता है और फ्लोट करने के लिए पॉइंटर लौटाता है। क्यूं कर ?क्योंकि C precedence rules() देना अर्थ * की तुलना में एक higer पूर्वता कि संकलक (float *)(f(float)) के रूप में यह समझना होगा। यही कारण है कि एक स्पष्ट कोष्टक पता चलता है कि (*f) समारोह सूचक है आवश्यक है।

3
float (*func(unsigned id))(float value); 

एक समारोह के घोषणा जो एक तर्क के रूप में एक अहस्ताक्षरित int लेता है और एक समारोह करने के लिए एक सूचक रिटर्न है।

समारोह (समारोह f) करने के लिए सूचक अंक तर्क के रूप में और रिटर्न नाव एक नाव ले जाता है जो करने के लिए। यह घोषणा है:

float f(float value); 

नाम func समारोह के:

float (*func(unsigned id))(float value); 
     ^^^^ 

तर्क समारोह func की: की

float (*func(unsigned id))(float value); 
      ^^^^^^^^^^^ 

वापसी प्रकार समारोह func:

float (*func())(float value); 

आप पूछा:: एक अभिव्यक्ति है कि कुछ सूचक का मूल्यांकन func(unsigned id): इसके अलावा, है

float (*func(unsigned id))(float value); 
    ^^^^^^^^     ^^^^^^^^^^^^^ 

तो समारोह कोई तर्क यह इस प्रकार दिखाई देगा था?

नहीं, यह नाम func और तर्क समारोह

की (unsigned id) है आप को देखने के लिए अब क्या func है शुरू कर रहे हैं? यह एक समारोह जो एक सूचक जो एक और घोषित समारोह के लिए अंक देता है।

मैंने उस कोड को शामिल किया जिसमें आप स्पष्ट रूप से देख सकते हैं कि f फ़ंक्शन के संदर्भ की तुलना में func फ़ंक्शन का वापसी मूल्य क्या है।

#include <stdio.h> 

float f(float value); 
float (*func(unsigned id))(float value); 

int main() 
{ 

    /* print the address of the f function 
    * using the return value of function func 
    */ 
    printf("func return value: %p\n\n", func(2)); 




     /* print the address of the f function referencing 
     * its address 
     */ 
    printf("referencing f address: %p\n", &f); 

    return 0; 
} 

float (*func(unsigned id))(float value) 
{ 
    printf("Original function with argument id = %d called\n", id); 
    return f; 
} 

float f(float value) 
{ 
    printf("f function\n"); 
    return 0.1; 
} 
5

इस कदम-दर-कदम मदद से C gibberish ↔ English

float (*func(unsigned id))(float value) { ... } 

पहले से ले लो कि गंधा वेब साइट के रूप में "च" के साथ "समारोह" की जगह "समारोह" के साथ परेशानी है और फिर पैरामीटर को निकालने नाम।

float (*f(unsigned))(float) 
// declare f as function (unsigned) returning pointer to function (float) returning float 

इस से, f समारोह घोषणा है कि एक unsigned id लेता है। यही कारण है कि f(unsigned) हिस्सा है।

यह एक चर x देता है जैसे कि इसे float (*x)(float) घोषित किया गया था। इसका पहला भाग, ओपी के रूप में देखा गया है, समारोह की मूल घोषणा में दूसरे छमाही से अलग है।

"समारोह" का उपयोग नहीं करने के लिए

उदाहरण याद है कि साइट के साथ प्रयोग का सुझाव:

int f2(unsigned); 
// declare f2 as function (unsigned) returning int 
int (*f3(unsigned)); 
// declare f3 as function (unsigned) returning pointer to int 
int (*f4)(unsigned); 
// declare f4 as pointer to function (unsigned) returning int 
int (*f5(unsigned))(char); 
// declare f5 as function (unsigned) returning pointer to function (char) returning int 
+0

बहुत अच्छा! तो आपका 'एफ 3' सिर्फ विस्तारित रूप है कि हम सभी इसे कैसे जानते हैं - 'int * f3 (unsigned)'? –

+0

@barak manos हाँ - वही। जोड़ा गया 'f3' क्योंकि यह ओपी के '(* func (unsigned id) को समझाने में मदद करेगा)। – chux

+0

समझ गया। कभी फंक्शन-पॉइंटर वापस नहीं करना पड़ा। मुझे लगता है कि यही कारण है कि वाक्यविन्यास इतना अपठनीय लग रहा था। वैसे भी ऐसा करने के लिए यह बहुत व्यर्थ लगता है। मैं वास्तव में किसी भी परिदृश्य के बारे में सोच नहीं सकता जिसमें मुझे फ़ंक्शन-पॉइंटर वापस करने की आवश्यकता होगी ... धन्यवाद –

संबंधित मुद्दे