c - 在C中,傳遞函數或傳遞函數指針?

  显示原文与译文双语对照的内容
關閉這個問題需要更多專註,它目前不接受答案想改進這個問題?更新問題,使它只針對一個問題編輯此帖子

2小時前

注意:鏈接另一個顯示函數指針示例的答案沒有幫助。問題是關於不同答案中展示的多種方法,並試圖理解它們之間的區別)

上下文:

我試圖理解在C(無C++ )中將函數作為參數傳遞給另一個函數的正確方法,我看到過幾種不同的方法,不同的方法我不清楚。

我在運行macOS

編譯器是GCC:


$ gcc --version


Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1


Apple LLVM version 10.0.1 (clang-1001.0.46.4)


Target: x86_64-apple-darwin18.7.0


Thread model: posix


InstalledDir: /Library/Developer/CommandLineTools/usr/bin



我在Makefile中使用CFLAGS=-Wall -g -O0

代碼示例

以下4段都生成相同的結果(至少相同的可見輸出),注意,在聲明和調用execute函數時,示例之間的惟一區別是,我已經在引號中包括了我最初調用每個示例的方法,只是為了區分它們(所以命名可能不對)。

它們實際上是4個排列:

  • 將函數execute聲明為接收void f()void (*f)()
  • execute(print)execute(&print)調用函數execute

注意,在所有情況下,函數都是用f()調用的,而不是使用(*f)(),但是,我還用(*f)()測試過,結果是相同的。8個排列,實際上(為了簡潔,這裡只顯示4)

  • Fragment 1:沒有指針的傳遞,沒有指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void f()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段2:與指針一起傳遞,並使用指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • Fragment 3:傳遞一個指針,並且沒有指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段4:沒有指針的傳遞和指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    

對於所有示例:

  • 程序編譯,並運行,沒有錯誤或警告
  • Hello列印正確
  • %p中列印的值在第一個和第二個列印中相同
  • sizeof在第一次列印時總是1
  • 在第二個列印中,sizeof總是8

我讀了什麼

我已經閱讀了幾個示例(Wikipedia,StackOverflow,StackOverflow答案中鏈接的其他資源),其中很多示例顯示了不同的示例,問題就是為了理解這些差異。

wikipedia關於函數指針的文章顯示了與snippet 4(由我簡化)類似的示例:


#include <math.h>


#include <stdio.h>



double compute_sum(double (*funcp)(double), double lo, double hi) {


 // ... more code


 double y = funcp(x);


 // ... more code


}



int main(void) {


 compute_sum(sin, 0.0, 1.0);


 compute_sum(cos, 0.0, 1.0);


 return 0;


}



  • 參數作為compute_sum(sin, 0.0, 1.0)傳遞(在sin上沒有& )
  • 參數被聲明為double (*funcp)(double) (* )
  • 參數被調用為funcp(x) (沒有*,因此沒有(*funcp)(x) )

Wikipedia文章後面的一個示例告訴我們,傳遞函數時的&是不需要的,沒有進一步的說明:


// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.


int F(char c);



// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.


typedef int Fn(char c);



// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.


Fn *fn = &F; // Note '&' not required - but it highlights what is being done.



// ... more code



// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result


int Call(Fn *fn, char c) {


 return fn(c);


} // Call(fn, c)



// This calls function 'Call', passing in 'F' and assigning the result to 'call'


int call = Call(&F, 'A'); // Again, '&' is not required



// ... more code



  • 參數作為Call(&F,'A')傳遞(在F上使用& )
  • 參數被聲明為Fn *fn (* )
  • 參數被調用為fn(c) (沒有(*fn) )

這個答案

  • 參數作為func(print)傳遞(在print上沒有& )
  • 參數被聲明為void (*f)(int) (* )
  • 參數被調用為(*f)(ctr) (使用(*fn) )

這個答案顯示了2個示例:

  • 第一種方法類似於代碼片段1:
    • 參數作為execute(print) (沒有& )傳遞
    • 參數被聲明為void f() (沒有* )
    • 參數被調用為f() (沒有* )
  • 第二個代碼片段類似於代碼片段2:
    • 參數作為execute(&print) (& )傳遞
    • 參數被聲明為void (*f)() (* )
    • 參數被調用為f()(沒有*)

這個答案

  • 沒有關於如何傳遞function argument (with or without & )的例子
  • 參數被聲明為int (*functionPtr)(int, int) (* )
  • 參數被調用為(*functionPtr)(2, 3) (使用* )

我一個答案里找到的這些鏈接材料(實際上是C++,但它沒有使用特定於C++的函數指針):

  • 參數作為&Minus (& )傳遞
  • 參數被聲明為float (*pt2Func)(float, float) (* )
  • 參數被調用為pt2Func(a, b) (沒有* )

我在這裡提供了7個例子,它們提供了至少5種使用或不使用& =�m쌧和*的組合,

我從這些中了解到什麼

我相信上一節已經表明,對於StackOverflow上最相關的問題/答案以及我鏈接的其他材料(其中大多數都是在StackOverflow的答案中鏈接的)沒有達成一致的解釋。

所有這些4種方法都由編譯器處理,或者存在非常微妙的差異,這些差異不會出現在這樣的簡單示例中。

我明白為什麼第二個列印輸出sizeof(f)8片段中的2和4,這是64-bit系統中的指針大小。但我不明白為什麼第二次列印會列印指針的大小,即使在o�n���G��m쌧函數聲明參數時沒有*圓括弧_eauc43onfyghzluomqidbzscamzafeqa8888_yfr_括弧的情況下,也不明白為什麼在第一次列印中函數變數有1G��m쌧,

  • 所有4段之間是否有實際的差異?為什麼它們的行為完全一樣?
  • 如果存在實際的運行時差異,你能解釋一下它們中發生了什麼?
  • 如果沒有運行時的區別,你能解釋一下編譯器在每種情況下都做了什麼,使它們的行為都相同(我假設編譯器會看到f(myF}�e!G��m쌧,並實際使用f(&anm�ձ�����2�,或類似的東西,,我想知道哪個是""方法)
  • 我應該使用哪一個4段,為什麼?
  • 我應該用f()(*f)()調用通過參數接收的傳遞函數?
  • 為什麼在每個片段的第一次列印中,function variable ( sizeof(print) )的大小總是1?我們怎麼知道這個箱子的大小?顯然不是指針的大小,在64-bit機器中,它應該是8位元組,如果使用sizeof(&print),我會得到指針的大小
  • 為什麼在片段1和3上,在第二個列印中,sizeof(f)提供8(指針的大小),即使參數是

回答時,請試著打破後面的數字問題)

时间:

關閉這個問題需要更多專註,它目前不接受答案想改進這個問題?更新問題,使它只針對一個問題編輯此帖子

2小時前

注意:鏈接另一個顯示函數指針示例的答案沒有幫助。問題是關於不同答案中展示的多種方法,並試圖理解它們之間的區別)

上下文:

我試圖理解在C(無C++ )中將函數作為參數傳遞給另一個函數的正確方法,我看到過幾種不同的方法,不同的方法我不清楚。

我在運行macOS

編譯器是GCC:


$ gcc --version


Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1


Apple LLVM version 10.0.1 (clang-1001.0.46.4)


Target: x86_64-apple-darwin18.7.0


Thread model: posix


InstalledDir: /Library/Developer/CommandLineTools/usr/bin



我在Makefile中使用CFLAGS=-Wall -g -O0

代碼示例

以下4段都生成相同的結果(至少相同的可見輸出),注意,在聲明和調用execute函數時,示例之間的惟一區別是,我已經在引號中包括了我最初調用每個示例的方法,只是為了區分它們(所以命名可能不對)。

它們實際上是4個排列:

  • 將函數execute聲明為接收void f()void (*f)()
  • execute(print)execute(&print)調用函數execute

注意,在所有情況下,函數都是用f()調用的,而不是使用(*f)(),但是,我還用(*f)()測試過,結果是相同的。8個排列,實際上(為了簡潔,這裡只顯示4)

  • Fragment 1:沒有指針的傳遞,沒有指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void f()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段2:與指針一起傳遞,並使用指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • Fragment 3:傳遞一個指針,並且沒有指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段4:沒有指針的傳遞和指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    

對於所有示例:

  • 程序編譯,並運行,沒有錯誤或警告
  • Hello列印正確
  • %p中列印的值在第一個和第二個列印中相同
  • sizeof在第一次列印時總是1
  • 在第二個列印中,sizeof總是8

我讀了什麼

我已經閱讀了幾個示例(Wikipedia,StackOverflow,StackOverflow答案中鏈接的其他資源),其中很多示例顯示了不同的示例,問題就是為了理解這些差異。

wikipedia關於函數指針的文章顯示了與snippet 4(由我簡化)類似的示例:


#include <math.h>


#include <stdio.h>



double compute_sum(double (*funcp)(double), double lo, double hi) {


 // ... more code


 double y = funcp(x);


 // ... more code


}



int main(void) {


 compute_sum(sin, 0.0, 1.0);


 compute_sum(cos, 0.0, 1.0);


 return 0;


}



  • 參數作為compute_sum(sin, 0.0, 1.0)傳遞(在sin上沒有& )
  • 參數被聲明為double (*funcp)(double) (* )
  • 參數被調用為funcp(x) (沒有*,因此沒有(*funcp)(x) )

Wikipedia文章後面的一個示例告訴我們,傳遞函數時的&是不需要的,沒有進一步的說明:


// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.


int F(char c);



// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.


typedef int Fn(char c);



// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.


Fn *fn = &F; // Note '&' not required - but it highlights what is being done.



// ... more code



// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result


int Call(Fn *fn, char c) {


 return fn(c);


} // Call(fn, c)



// This calls function 'Call', passing in 'F' and assigning the result to 'call'


int call = Call(&F, 'A'); // Again, '&' is not required



// ... more code



  • 參數作為Call(&F,'A')傳遞(在F上使用& )
  • 參數被聲明為Fn *fn (* )
  • 參數被調用為fn(c) (沒有(*fn) )

這個答案

  • 參數作為func(print)傳遞(在print上沒有& )
  • 參數被聲明為void (*f)(int) (* )
  • 參數被調用為(*f)(ctr) (使用(*fn) )

這個答案顯示了2個示例:

  • 第一種方法類似於代碼片段1:
    • 參數作為execute(print) (沒有& )傳遞
    • 參數被聲明為void f() (沒有* )
    • 參數被調用為f() (沒有* )
  • 第二個代碼片段類似於代碼片段2:
    • 參數作為execute(&print) (& )傳遞
    • 參數被聲明為void (*f)() (* )
    • 參數被調用為f()(沒有*)

這個答案

  • 沒有關於如何傳遞function argument (with or without & )的例子
  • 參數被聲明為int (*functionPtr)(int, int) (* )
  • 參數被調用為(*functionPtr)(2, 3) (使用* )

我一個答案里找到的這些鏈接材料(實際上是C++,但它沒有使用特定於C++的函數指針):

  • 參數作為&Minus (& )傳遞
  • 參數被聲明為float (*pt2Func)(float, float) (* )
  • 參數被調用為pt2Func(a, b) (沒有* )

我在這裡提供了7個例子,它們提供了至少5種使用或不使用& =�m쌧和*的組合,

我從這些中了解到什麼

我相信上一節已經表明,對於StackOverflow上最相關的問題/答案以及我鏈接的其他材料(其中大多數都是在StackOverflow的答案中鏈接的)沒有達成一致的解釋。

所有這些4種方法都由編譯器處理,或者存在非常微妙的差異,這些差異不會出現在這樣的簡單示例中。

我明白為什麼第二個列印輸出sizeof(f)8片段中的2和4,這是64-bit系統中的指針大小。但我不明白為什麼第二次列印會列印指針的大小,即使在o�n���G��m쌧函數聲明參數時沒有*圓括弧_eauc43onfyghzluomqidbzscamzafeqa8888_yfr_括弧的情況下,也不明白為什麼在第一次列印中函數變數有1G��m쌧,

  • 所有4段之間是否有實際的差異?為什麼它們的行為完全一樣?
  • 如果存在實際的運行時差異,你能解釋一下它們中發生了什麼?
  • 如果沒有運行時的區別,你能解釋一下編譯器在每種情況下都做了什麼,使它們的行為都相同(我假設編譯器會看到f(myF}�e!G��m쌧,並實際使用f(&anm�ձ�����2�,或類似的東西,,我想知道哪個是""方法)
  • 我應該使用哪一個4段,為什麼?
  • 我應該用f()(*f)()調用通過參數接收的傳遞函數?
  • 為什麼在每個片段的第一次列印中,function variable ( sizeof(print) )的大小總是1?我們怎麼知道這個箱子的大小?顯然不是指針的大小,在64-bit機器中,它應該是8位元組,如果使用sizeof(&print),我會得到指針的大小
  • 為什麼在片段1和3上,在第二個列印中,sizeof(f)提供8(指針的大小),即使參數是

回答時,請試著打破後面的數字問題)

關閉這個問題需要更多專註,它目前不接受答案想改進這個問題?更新問題,使它只針對一個問題編輯此帖子

2小時前

注意:鏈接另一個顯示函數指針示例的答案沒有幫助。問題是關於不同答案中展示的多種方法,並試圖理解它們之間的區別)

上下文:

我試圖理解在C(無C++ )中將函數作為參數傳遞給另一個函數的正確方法,我看到過幾種不同的方法,不同的方法我不清楚。

我在運行macOS

編譯器是GCC:


$ gcc --version


Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1


Apple LLVM version 10.0.1 (clang-1001.0.46.4)


Target: x86_64-apple-darwin18.7.0


Thread model: posix


InstalledDir: /Library/Developer/CommandLineTools/usr/bin



我在Makefile中使用CFLAGS=-Wall -g -O0

代碼示例

以下4段都生成相同的結果(至少相同的可見輸出),注意,在聲明和調用execute函數時,示例之間的惟一區別是,我已經在引號中包括了我最初調用每個示例的方法,只是為了區分它們(所以命名可能不對)。

它們實際上是4個排列:

  • 將函數execute聲明為接收void f()void (*f)()
  • execute(print)execute(&print)調用函數execute

注意,在所有情況下,函數都是用f()調用的,而不是使用(*f)(),但是,我還用(*f)()測試過,結果是相同的。8個排列,實際上(為了簡潔,這裡只顯示4)

  • Fragment 1:沒有指針的傳遞,沒有指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void f()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段2:與指針一起傳遞,並使用指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • Fragment 3:傳遞一個指針,並且沒有指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段4:沒有指針的傳遞和指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    

對於所有示例:

  • 程序編譯,並運行,沒有錯誤或警告
  • Hello列印正確
  • %p中列印的值在第一個和第二個列印中相同
  • sizeof在第一次列印時總是1
  • 在第二個列印中,sizeof總是8

我讀了什麼

我已經閱讀了幾個示例(Wikipedia,StackOverflow,StackOverflow答案中鏈接的其他資源),其中很多示例顯示了不同的示例,問題就是為了理解這些差異。

wikipedia關於函數指針的文章顯示了與snippet 4(由我簡化)類似的示例:


#include <math.h>


#include <stdio.h>



double compute_sum(double (*funcp)(double), double lo, double hi) {


 // ... more code


 double y = funcp(x);


 // ... more code


}



int main(void) {


 compute_sum(sin, 0.0, 1.0);


 compute_sum(cos, 0.0, 1.0);


 return 0;


}



  • 參數作為compute_sum(sin, 0.0, 1.0)傳遞(在sin上沒有& )
  • 參數被聲明為double (*funcp)(double) (* )
  • 參數被調用為funcp(x) (沒有*,因此沒有(*funcp)(x) )

Wikipedia文章後面的一個示例告訴我們,傳遞函數時的&是不需要的,沒有進一步的說明:


// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.


int F(char c);



// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.


typedef int Fn(char c);



// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.


Fn *fn = &F; // Note '&' not required - but it highlights what is being done.



// ... more code



// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result


int Call(Fn *fn, char c) {


 return fn(c);


} // Call(fn, c)



// This calls function 'Call', passing in 'F' and assigning the result to 'call'


int call = Call(&F, 'A'); // Again, '&' is not required



// ... more code



  • 參數作為Call(&F,'A')傳遞(在F上使用& )
  • 參數被聲明為Fn *fn (* )
  • 參數被調用為fn(c) (沒有(*fn) )

這個答案

  • 參數作為func(print)傳遞(在print上沒有& )
  • 參數被聲明為void (*f)(int) (* )
  • 參數被調用為(*f)(ctr) (使用(*fn) )

這個答案顯示了2個示例:

  • 第一種方法類似於代碼片段1:
    • 參數作為execute(print) (沒有& )傳遞
    • 參數被聲明為void f() (沒有* )
    • 參數被調用為f() (沒有* )
  • 第二個代碼片段類似於代碼片段2:
    • 參數作為execute(&print) (& )傳遞
    • 參數被聲明為void (*f)() (* )
    • 參數被調用為f()(沒有*)

這個答案

  • 沒有關於如何傳遞function argument (with or without & )的例子
  • 參數被聲明為int (*functionPtr)(int, int) (* )
  • 參數被調用為(*functionPtr)(2, 3) (使用* )

我一個答案里找到的這些鏈接材料(實際上是C++,但它沒有使用特定於C++的函數指針):

  • 參數作為&Minus (& )傳遞
  • 參數被聲明為float (*pt2Func)(float, float) (* )
  • 參數被調用為pt2Func(a, b) (沒有* )

我在這裡提供了7個例子,它們提供了至少5種使用或不使用& =�m쌧和*的組合,

我從這些中了解到什麼

我相信上一節已經表明,對於StackOverflow上最相關的問題/答案以及我鏈接的其他材料(其中大多數都是在StackOverflow的答案中鏈接的)沒有達成一致的解釋。

所有這些4種方法都由編譯器處理,或者存在非常微妙的差異,這些差異不會出現在這樣的簡單示例中。

我明白為什麼第二個列印輸出sizeof(f)8片段中的2和4,這是64-bit系統中的指針大小。但我不明白為什麼第二次列印會列印指針的大小,即使在o�n���G��m쌧函數聲明參數時沒有*圓括弧_eauc43onfyghzluomqidbzscamzafeqa8888_yfr_括弧的情況下,也不明白為什麼在第一次列印中函數變數有1G��m쌧,

  • 所有4段之間是否有實際的差異?為什麼它們的行為完全一樣?
  • 如果存在實際的運行時差異,你能解釋一下它們中發生了什麼?
  • 如果沒有運行時的區別,你能解釋一下編譯器在每種情況下都做了什麼,使它們的行為都相同(我假設編譯器會看到f(myF}�e!G��m쌧,並實際使用f(&anm�ձ�����2�,或類似的東西,,我想知道哪個是""方法)
  • 我應該使用哪一個4段,為什麼?
  • 我應該用f()(*f)()調用通過參數接收的傳遞函數?
  • 為什麼在每個片段的第一次列印中,function variable ( sizeof(print) )的大小總是1?我們怎麼知道這個箱子的大小?顯然不是指針的大小,在64-bit機器中,它應該是8位元組,如果使用sizeof(&print),我會得到指針的大小
  • 為什麼在片段1和3上,在第二個列印中,sizeof(f)提供8(指針的大小),即使參數是

回答時,請試著打破後面的數字問題)

關閉這個問題需要更多專註,它目前不接受答案想改進這個問題?更新問題,使它只針對一個問題編輯此帖子

2小時前

注意:鏈接另一個顯示函數指針示例的答案沒有幫助。問題是關於不同答案中展示的多種方法,並試圖理解它們之間的區別)

上下文:

我試圖理解在C(無C++ )中將函數作為參數傳遞給另一個函數的正確方法,我看到過幾種不同的方法,不同的方法我不清楚。

我在運行macOS

編譯器是GCC:


$ gcc --version


Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1


Apple LLVM version 10.0.1 (clang-1001.0.46.4)


Target: x86_64-apple-darwin18.7.0


Thread model: posix


InstalledDir: /Library/Developer/CommandLineTools/usr/bin



我在Makefile中使用CFLAGS=-Wall -g -O0

代碼示例

以下4段都生成相同的結果(至少相同的可見輸出),注意,在聲明和調用execute函數時,示例之間的惟一區別是,我已經在引號中包括了我最初調用每個示例的方法,只是為了區分它們(所以命名可能不對)。

它們實際上是4個排列:

  • 將函數execute聲明為接收void f()void (*f)()
  • execute(print)execute(&print)調用函數execute

注意,在所有情況下,函數都是用f()調用的,而不是使用(*f)(),但是,我還用(*f)()測試過,結果是相同的。8個排列,實際上(為了簡潔,這裡只顯示4)

  • Fragment 1:沒有指針的傳遞,沒有指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void f()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段2:與指針一起傳遞,並使用指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • Fragment 3:傳遞一個指針,並且沒有指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段4:沒有指針的傳遞和指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    

對於所有示例:

  • 程序編譯,並運行,沒有錯誤或警告
  • Hello列印正確
  • %p中列印的值在第一個和第二個列印中相同
  • sizeof在第一次列印時總是1
  • 在第二個列印中,sizeof總是8

我讀了什麼

我已經閱讀了幾個示例(Wikipedia,StackOverflow,StackOverflow答案中鏈接的其他資源),其中很多示例顯示了不同的示例,問題就是為了理解這些差異。

wikipedia關於函數指針的文章顯示了與snippet 4(由我簡化)類似的示例:


#include <math.h>


#include <stdio.h>



double compute_sum(double (*funcp)(double), double lo, double hi) {


 // ... more code


 double y = funcp(x);


 // ... more code


}



int main(void) {


 compute_sum(sin, 0.0, 1.0);


 compute_sum(cos, 0.0, 1.0);


 return 0;


}



  • 參數作為compute_sum(sin, 0.0, 1.0)傳遞(在sin上沒有& )
  • 參數被聲明為double (*funcp)(double) (* )
  • 參數被調用為funcp(x) (沒有*,因此沒有(*funcp)(x) )

Wikipedia文章後面的一個示例告訴我們,傳遞函數時的&是不需要的,沒有進一步的說明:


// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.


int F(char c);



// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.


typedef int Fn(char c);



// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.


Fn *fn = &F; // Note '&' not required - but it highlights what is being done.



// ... more code



// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result


int Call(Fn *fn, char c) {


 return fn(c);


} // Call(fn, c)



// This calls function 'Call', passing in 'F' and assigning the result to 'call'


int call = Call(&F, 'A'); // Again, '&' is not required



// ... more code



  • 參數作為Call(&F,'A')傳遞(在F上使用& )
  • 參數被聲明為Fn *fn (* )
  • 參數被調用為fn(c) (沒有(*fn) )

這個答案

  • 參數作為func(print)傳遞(在print上沒有& )
  • 參數被聲明為void (*f)(int) (* )
  • 參數被調用為(*f)(ctr) (使用(*fn) )

這個答案顯示了2個示例:

  • 第一種方法類似於代碼片段1:
    • 參數作為execute(print) (沒有& )傳遞
    • 參數被聲明為void f() (沒有* )
    • 參數被調用為f() (沒有* )
  • 第二個代碼片段類似於代碼片段2:
    • 參數作為execute(&print) (& )傳遞
    • 參數被聲明為void (*f)() (* )
    • 參數被調用為f()(沒有*)

這個答案

  • 沒有關於如何傳遞function argument (with or without & )的例子
  • 參數被聲明為int (*functionPtr)(int, int) (* )
  • 參數被調用為(*functionPtr)(2, 3) (使用* )

我一個答案里找到的這些鏈接材料(實際上是C++,但它沒有使用特定於C++的函數指針):

  • 參數作為&Minus (& )傳遞
  • 參數被聲明為float (*pt2Func)(float, float) (* )
  • 參數被調用為pt2Func(a, b) (沒有* )

我在這裡提供了7個例子,它們提供了至少5種使用或不使用& =�m쌧和*的組合,

我從這些中了解到什麼

我相信上一節已經表明,對於StackOverflow上最相關的問題/答案以及我鏈接的其他材料(其中大多數都是在StackOverflow的答案中鏈接的)沒有達成一致的解釋。

所有這些4種方法都由編譯器處理,或者存在非常微妙的差異,這些差異不會出現在這樣的簡單示例中。

我明白為什麼第二個列印輸出sizeof(f)8片段中的2和4,這是64-bit系統中的指針大小。但我不明白為什麼第二次列印會列印指針的大小,即使在o�n���G��m쌧函數聲明參數時沒有*圓括弧_eauc43onfyghzluomqidbzscamzafeqa8888_yfr_括弧的情況下,也不明白為什麼在第一次列印中函數變數有1G��m쌧,

  • 所有4段之間是否有實際的差異?為什麼它們的行為完全一樣?
  • 如果存在實際的運行時差異,你能解釋一下它們中發生了什麼?
  • 如果沒有運行時的區別,你能解釋一下編譯器在每種情況下都做了什麼,使它們的行為都相同(我假設編譯器會看到f(myF}�e!G��m쌧,並實際使用f(&anm�ձ�����2�,或類似的東西,,我想知道哪個是""方法)
  • 我應該使用哪一個4段,為什麼?
  • 我應該用f()(*f)()調用通過參數接收的傳遞函數?
  • 為什麼在每個片段的第一次列印中,function variable ( sizeof(print) )的大小總是1?我們怎麼知道這個箱子的大小?顯然不是指針的大小,在64-bit機器中,它應該是8位元組,如果使用sizeof(&print),我會得到指針的大小
  • 為什麼在片段1和3上,在第二個列印中,sizeof(f)提供8(指針的大小),即使參數是

回答時,請試著打破後面的數字問題)

關閉這個問題需要更多專註,它目前不接受答案想改進這個問題?更新問題,使它只針對一個問題編輯此帖子

2小時前

注意:鏈接另一個顯示函數指針示例的答案沒有幫助。問題是關於不同答案中展示的多種方法,並試圖理解它們之間的區別)

上下文:

我試圖理解在C(無C++ )中將函數作為參數傳遞給另一個函數的正確方法,我看到過幾種不同的方法,不同的方法我不清楚。

我在運行macOS

編譯器是GCC:


$ gcc --version


Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1


Apple LLVM version 10.0.1 (clang-1001.0.46.4)


Target: x86_64-apple-darwin18.7.0


Thread model: posix


InstalledDir: /Library/Developer/CommandLineTools/usr/bin



我在Makefile中使用CFLAGS=-Wall -g -O0

代碼示例

以下4段都生成相同的結果(至少相同的可見輸出),注意,在聲明和調用execute函數時,示例之間的惟一區別是,我已經在引號中包括了我最初調用每個示例的方法,只是為了區分它們(所以命名可能不對)。

它們實際上是4個排列:

  • 將函數execute聲明為接收void f()void (*f)()
  • execute(print)execute(&print)調用函數execute

注意,在所有情況下,函數都是用f()調用的,而不是使用(*f)(),但是,我還用(*f)()測試過,結果是相同的。8個排列,實際上(為了簡潔,這裡只顯示4)

  • Fragment 1:沒有指針的傳遞,沒有指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void f()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段2:與指針一起傳遞,並使用指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • Fragment 3:傳遞一個指針,並且沒有指針接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(&print);
    
    
     return 0;
    
    
    }
    
    
    
    
  • 代碼片段4:沒有指針的傳遞和指針的接收"

    
    #include <stdio.h>
    
    
    
    void execute(void (*f)()) {
    
    
     printf("2 %p %lun", f, sizeof(f));
    
    
     f();
    
    
    }
    
    
    
    void print() {
    
    
     printf("Hello!n");
    
    
    }
    
    
    
    int main() {
    
    
     printf("1 %p %lun", print, sizeof(print));
    
    
     execute(print);
    
    
     return 0;
    
    
    }
    
    
    
    

對於所有示例:

  • 程序編譯,並運行,沒有錯誤或警告
  • Hello列印正確
  • %p中列印的值在第一個和第二個列印中相同
  • sizeof在第一次列印時總是1
  • 在第二個列印中,sizeof總是8

我讀了什麼

我已經閱讀了幾個示例(Wikipedia,StackOverflow,StackOverflow答案中鏈接的其他資源),其中很多示例顯示了不同的示例,問題就是為了理解這些差異。

wikipedia關於函數指針的文章顯示了與snippet 4(由我簡化)類似的示例:


#include <math.h>


#include <stdio.h>



double compute_sum(double (*funcp)(double), double lo, double hi) {


 // ... more code


 double y = funcp(x);


 // ... more code


}



int main(void) {


 compute_sum(sin, 0.0, 1.0);


 compute_sum(cos, 0.0, 1.0);


 return 0;


}



  • 參數作為compute_sum(sin, 0.0, 1.0)傳遞(在sin上沒有& )
  • 參數被聲明為double (*funcp)(double) (* )
  • 參數被調用為funcp(x) (沒有*,因此沒有(*funcp)(x) )

Wikipedia文章後面的一個示例告訴我們,傳遞函數時的&是不需要的,沒有進一步的說明:


// This declares 'F', a function that accepts a 'char' and returns an 'int'. Definition is elsewhere.


int F(char c);



// This defines 'Fn', a type of function that accepts a 'char' and returns an 'int'.


typedef int Fn(char c);



// This defines 'fn', a variable of type pointer-to-'Fn', and assigns the address of 'F' to it.


Fn *fn = &F; // Note '&' not required - but it highlights what is being done.



// ... more code



// This defines 'Call', a function that accepts a pointer-to-'Fn', calls it, and returns the result


int Call(Fn *fn, char c) {


 return fn(c);


} // Call(fn, c)



// This calls function 'Call', passing in 'F' and assigning the result to 'call'


int call = Call(&F, 'A'); // Again, '&' is not required



// ... more code



  • 參數作為Call(&F,'A')傳遞(在F上使用& )
  • 參數被聲明為Fn *fn (* )
  • 參數被調用為fn(c) (沒有(*fn) )

這個答案

  • 參數作為func(print)傳遞(在print上沒有& )
  • 參數被聲明為void (*f)(int) (* )
  • 參數被調用為(*f)(ctr) (使用(*fn) )

這個答案顯示了2個示例:

  • 第一種方法類似於代碼片段1:
    • 參數作為execute(print) (沒有& )傳遞
    • 參數被聲明為void f() (沒有* )
    • 參數被調用為f() (沒有* )
  • 第二個代碼片段類似於代碼片段2:
    • 參數作為execute(&print) (& )傳遞
    • 參數被聲明為void (*f)() (* )
    • 參數被調用為f()(沒有*)

這個答案

  • 沒有關於如何傳遞function argument (with or without & )的例子
  • 參數被聲明為int (*functionPtr)(int, int) (* )
  • 參數被調用為(*functionPtr)(2, 3) (使用* )

我一個答案里找到的這些鏈接材料(實際上是C++,但它沒有使用特定於C++的函數指針):

  • 參數作為&Minus (& )傳遞
  • 參數被聲明為float (*pt2Func)(float, float) (* )
  • 參數被調用為pt2Func(a, b) (沒有* )

我在這裡提供了7個例子,它們提供了至少5種使用或不使用& =�m쌧和*的組合,

我從這些中了解到什麼

我相信上一節已經表明,對於StackOverflow上最相關的問題/答案以及我鏈接的其他材料(其中大多數都是在StackOverflow的答案中鏈接的)沒有達成一致的解釋。

所有這些4種方法都由編譯器處理,或者存在非常微妙的差異,這些差異不會出現在這樣的簡單示例中。

我明白為什麼第二個列印輸出sizeof(f)8片段中的2和4,這是64-bit系統中的指針大小。但我不明白為什麼第二次列印會列印指針的大小,即使在o�n���G��m쌧函數聲明參數時沒有*圓括弧_eauc43onfyghzluomqidbzscamzafeqa8888_yfr_括弧的情況下,也不明白為什麼在第一次列印中函數變數有1G��m쌧,

  • 所有4段之間是否有實際的差異?為什麼它們的行為完全一樣?
  • 如果存在實際的運行時差異,你能解釋一下它們中發生了什麼?
  • 如果沒有運行時的區別,你能解釋一下編譯器在每種情況下都做了什麼,使它們的行為都相同(我假設編譯器會看到f(myF}�e!G��m쌧,並實際使用f(&anm�ձ�����2�,或類似的東西,,我想知道哪個是""方法)
  • 我應該使用哪一個4段,為什麼?
  • 我應該用f()(*f)()調用通過參數接收的傳遞函數?
  • 為什麼在每個片段的第一次列印中,function variable ( sizeof(print) )的大小總是1?我們怎麼知道這個箱子的大小?顯然不是指針的大小,在64-bit機器中,它應該是8位元組,如果使用sizeof(&print),我會得到指針的大小
  • 為什麼在片段1和3上,在第二個列印中,sizeof(f)提供8(指針的大小),即使參數是

回答時,請試著打破後面的數字問題)

...