欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言中的函數(shù)指針學(xué)習(xí)筆記

 更新時間:2016年04月20日 15:45:55   作者:渣渣一個  
這篇文章主要介紹了C語言中的函數(shù)指針的一些學(xué)習(xí)知識點記錄,文中作者整理了一些比較interesting的函數(shù)指針用法,需要的朋友可以參考下

一、定義函數(shù)指針

return_type (*func_pointer)(parameter_list)

普通指針變量的定義

int * p;
char * pointer;

類型的限定都在變量前面;
函數(shù)指針類型的限定是前后都有,前面是返回類型,后面是輸入?yún)?shù)。

2016420154232853.png (449×127)

利用typedef 可以簡化上面的表達方式。

typedef return_type (*FunctionPointer) (parameter_list);
FunctionPointer func_pointer;

這樣是不是容易讀了,和上面的功能一樣,定義了一個返回類型為return_type ,輸入?yún)?shù)為parameter_list的函數(shù)指針。

二、定義返回函數(shù)指針的函數(shù)
return_type(*function(func_parameter_list))(parameter_list)

2016420154256143.png (558×129)

方框圈出來的表示返回類型為函數(shù)指針,剩下的部分就表示一個function函數(shù),輸入?yún)?shù)為func_parameter_list。
它就等價于 FunctionPointer function(func_parameter_list); 。
再看看:

void ( *signal( int sig, void (* handler)( int )))( int );

2016420154323228.png (400×63)

signal是一個返回函數(shù)指針的函數(shù),signal的輸入為int 變量和一個函數(shù)指針。

三、函數(shù)指針的使用

#include <stdio.h> 
int add(int a, int b); 
void main() 
{ 
  int(*fun1)(int a, int b) = add; 
  int(*fun2)(int a, int b) = &add; 
  int(*fun3)(int a, int b) = *add; 

  printf("%d\n", fun1(1, 2)); 
  printf("%d\n", fun2(1, 2)); 
  printf("%d\n", fun3(1, 2)); 

  char input[10]; 
  gets(input); 
} 
int add(int a, int b) 
{ 
  return a + b; 
}

函數(shù)名會被隱式的轉(zhuǎn)變?yōu)橹羔?,前面?和&操作符都不起作用,printf的結(jié)果都是3。

四、神奇的代碼

int (*(*pf())())()
{ return nullptr; }

哇哦,這是個什么函數(shù)!畫個框框分解它

2016420154405912.png (400×63)

小框表示返回的是一個函數(shù)指針,在圈個大框,又是一個函數(shù)指針。
它就表示,pf() 返回的是一個函數(shù)指針,這個函數(shù)指針對應(yīng)一個無輸入?yún)?shù)的函數(shù):返回值也是函數(shù)指針(對應(yīng)無輸入?yún)?shù)的函數(shù),返回值為int類型)。好復(fù)雜啊,有點暈!
利用typedef 簡化一下。

typedef int(*Fun1) (); 
typedef Fun1(*Fun2) (); 
Fun2 pf() 
{ 
   return nullptr; 
}

這樣看就舒服多了。

五、這又是什么鬼!

(*(void(*) ())0)();

畫個框看看:

2016420154437319.png (299×61)

小框里代表一個函數(shù)指針,常數(shù)前面加括號代表類型的強制轉(zhuǎn)換。咦,它把0強制轉(zhuǎn)換成了一個函數(shù)指針,并執(zhí)行!這是什么操作??!
六、一段驗證代碼

#include <stdio.h> 
typedef int Function(int, int); 
typedef int(*FunctionPointer1) (int, int); 
typedef FunctionPointer1(*FunctionPointer2) (); 
int fun1(int a, int b) 
{ 
  return a + b; 
} 

FunctionPointer1 fun2() 
{ 
  return fun1; 
} 
FunctionPointer2 fun3() 
{ 
  return fun2; 
} 
int(*(*fun4())())(int, int) 
{ 
  return fun2; 
} 

void main() 
{ 
  Function* fuction = fun1; 
  FunctionPointer1 fun = fun1; 
  int a = fun3()()(3, 4); 
  int b = fun4()()(5, 6); 
  printf("%d\n%d\n", a, b); 
  printf("fun1:%d\n*fun1:%d\n&fun1:%d", fun1, *fun1, &fun1); 
  printf("fun:%d\n*fun:%d\n&fun:%d", fun, *fun, &fun); 
  char chars[10]; 
  gets(chars); 
}

函數(shù)名前面加不加*,&操作符,都是一個效果;函數(shù)指針前面加不加*操作符是一個效果,但是加上&操作符就代表著取指針的地址了。
可以通過typedef int Function(int, int); 為一種類型的函數(shù)定義別名,但是使用的時候只能定義指針形式的變量:

Function* fuction = fun1;

七、一個問題
在stackoverflow上偶爾看到如下的問題,代碼如下

#include
void hello() { printf("hello"); }
int hello_1()
{
    printf("hello 1");
    return 0;
}
 
int main(void) {
  (*****hello)();
  (****hello_1)();
}

   執(zhí)行結(jié)果是無論hello前面有多少個指針符號,都是執(zhí)行hello()函數(shù),打印“hello”。
  為什么出現(xiàn)這樣的結(jié)果呢:
    用指針指向一個函數(shù)是OK的,但是仍然還要被轉(zhuǎn)化為一個function pointer。其實使用*來指向一個函數(shù) == CALL這個函數(shù)。因此無論指向多少次,仍然也是調(diào)用這個函數(shù)。
為什么一個函數(shù)會被轉(zhuǎn)化成一個指針呢?答案就是將函數(shù)默認(rèn)的轉(zhuǎn)換成函數(shù)指針,可以減少&的使用,編譯器默認(rèn)的將函數(shù)轉(zhuǎn)化為函數(shù)指針,也省得你每次調(diào)用函數(shù)時加*調(diào)用函數(shù)。
  哈哈,也就是我們之前說的,函數(shù)即指針。似乎有點不是很清晰,再看下面的例子

void foo() {
    printf("Foo to you too!...\n");
};
 
int a = 2;
int* test()
{
    return &a;
}
int main()
{
  int i;
  void (*p1_foo)() = foo;
  void (*p2_foo)() = *foo;
  void (*p3_foo)() = &foo;
  void (*p4_foo)() = *&foo;
  void (*p5_foo)() = &*foo;
  void (*p6_foo)() = **foo;
  void (*p7_foo)() = **********************foo;
 
  (*p1_foo)();
  (*p2_foo)();
  (*p3_foo)();
  (*p4_foo)();
  (*p5_foo)();
  (*p6_foo)();
  (*p7_foo)();
  i = *(***test)();
printf("i=%d\n",i);
}

上面的列子不出例外,都能正常打印我們想要的數(shù)據(jù)。
但是對于&,則要進行仔細的分析一下:
&對于一個函數(shù)的操作,是返回一個指針,指向函數(shù)的指針,如果在對此指針執(zhí)行&也就是&&foo,則會返回error,因為&foo是一個指針數(shù)值,也就是一個rvalue類型,再對他進行&操作,顯然是返回error的。

&&foo  //EROOR
&*&*&*&*&*&*foo //OK
&******&foo  //OK

相關(guān)文章

最新評論