真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C語言函數(shù)指針知識點(diǎn)總結(jié)-創(chuàng)新互聯(lián)

這篇文章主要講解了“C語言函數(shù)指針知識點(diǎn)總結(jié)”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“C語言函數(shù)指針知識點(diǎn)總結(jié)”吧!

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)龍華,十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220

函數(shù)指針和一個簡單的函數(shù)

我們從一個非常簡單的”Hello World“函數(shù)入手,來見識一下怎樣創(chuàng)建一個函數(shù)指針。

1 2 3 4 5 6 7 8 9 10 11 12 13 14#include
 //
函數(shù)原型
void

sayHello();
 //函數(shù)實(shí)現(xiàn)void

sayHello(){
    printf("hello
world\n"
);} //
main函數(shù)調(diào)用
int

main() {
    sayHello();}

我們定義了一個名為sayHello的函數(shù),它沒有返回值也不接受任何參數(shù)。當(dāng)我們在main函數(shù)中調(diào)用它的時候,它向屏幕輸出出”hello world“。非常簡單。接下來,我們改寫一下main函數(shù),之前直接調(diào)用的sayHello函數(shù),現(xiàn)在改用函數(shù)指針來調(diào)用它。

1 2 3 4int

main() {
    void

(*sayHelloPtr)() = sayHello;
    (*sayHelloPtr)();}

第二行void (*sayHelloPtr)()的語法看起來有些奇怪,我們來一步一步分析。

  1. 這里,關(guān)鍵字void的作用是說我們創(chuàng)建了一個函數(shù)指針,并讓它指向了一個返回void(也就是沒有返回值)的函數(shù)。

  2. 就像其他任何指針都必須有一個名稱一樣,這里sayHelloPtr被當(dāng)作這個函數(shù)指針的名稱。

  3. 我們用*符號來表示這是一個指針,這跟聲明一個指向整數(shù)或者字符的指針沒有任何區(qū)別。

  4. *sayHelloPtr兩端的括號是必須的,否則,上述聲明變成void
    *sayHelloPtr()
    ,*會優(yōu)先跟void結(jié)合,變成了一個返回指向void的指針的普通函數(shù)的聲明。因此,函數(shù)指針聲明的時候不要忘記加上括號,這非常關(guān)鍵。

  5. 參數(shù)列表緊跟在指針名之后,這個例子中由于沒有參數(shù),所以是一對空括號()。

  6. 將上述要點(diǎn)結(jié)合起來,void (*syaHelloPtr)()的意義就非常清楚了,這是一個函數(shù)指針,它指向一個不接收參數(shù)且沒有返回值的函數(shù)。

在上面的第二行代碼,即void (*sayHelloPtr)() = sayHello;,我們將sayHello這個函數(shù)名賦給了我們新建的函數(shù)指針。關(guān)于函數(shù)名的更多細(xì)節(jié)我們會在下文中討論,現(xiàn)在暫時可以將其看作一個標(biāo)簽,它代表函數(shù)的地址,并且可以賦值給函數(shù)指針。這就跟語句int
*x = &myint;
中我們把myint的地址賦給一個指向整數(shù)的指針一樣。只是當(dāng)我們考慮函數(shù)的時候,我們不需要加上一個取地址符&。簡而言之,函數(shù)名就是它的地址。接著看第三行,我們用代碼’(*sayHelloPtr)();·‘解引用并調(diào)用了函數(shù)指針。

  1. 在第二行被聲明之后,sayHelloPtr作為函數(shù)指針的名稱,跟其他任何指針沒有差別,能夠儲值和賦值。

  2. 我們對sayHelloPtr解引用的方式也與其他任何指針一樣,即在指針之前使用解引用符*,也就是代碼中的*sayHelloPtr。

  3. 同樣的,我們需要在其兩端加上括號,即(*sayHelloPtr),否則它就不被當(dāng)做一個函數(shù)指針。因此,記得聲明和解引用的時候都要在兩端加上括號。

  4. 括號操作符用于C語言中的函數(shù)調(diào)用,如果有參數(shù)參與,就將其放入括號中。這對于函數(shù)指針也是相似的,即代碼中的(*sayHelloPtr)()。

  5. 這個函數(shù)沒有返回值,也就沒有必要將它賦值給任何變量。單獨(dú)來說,這個調(diào)用跟sayHello()沒什么兩樣。

接下來,我們再對函數(shù)稍加修改。你會看到函數(shù)指針奇怪的語法,以及用調(diào)用普通函數(shù)的方法來調(diào)用賦值后函數(shù)指針的現(xiàn)象。

1 2 3 4int

main() {
void

(*sayHelloPtr)() = sayHello;
sayHelloPtr();}

跟之前一樣,我們將sayHello函數(shù)賦給函數(shù)指針。但是這一次,我們用調(diào)用普通函數(shù)的方法調(diào)用了它。稍后討論函數(shù)名的時候我會解釋這一現(xiàn)象,現(xiàn)在只需要知道(*syaHelloPtr)()syaHelloPtr()是相同的即可。

簡單來說,函數(shù)指針,就是指向函數(shù)的指針;其核心是函數(shù)地址和函數(shù)原型

1 2 3 4 5 6 7 8void

sayHello(){
    printf("hello
world\n"
);} int

main() {
    void

(*sayHelloPtr)() = sayHello;
    (*sayHelloPtr)();}

上面的main函數(shù)如下來寫,更能體現(xiàn)函數(shù)指針的本質(zhì)

1 2 3 4 5int

main() {
    void

*ptr = NULL;
//
聲明一個指針
    prt
= sayhello;
//
指向一個函數(shù)
  (*
(
void

(*)()) ptr)();
//
調(diào)用函數(shù)指針,或者說以指定原型 進(jìn)行函數(shù)調(diào)用
}

void (*)() 是函數(shù)原型
((void (*)())ptr) 是將ptr轉(zhuǎn)換為 上面的原型
(*(void (*)())ptr)()是以指定原型進(jìn)行函數(shù)調(diào)用

理解上面這3步,函數(shù)指針就是:
(1)用一個指針記住函數(shù)地址,以便于后續(xù)使用
(2)需要使用時,用指定函數(shù)原型進(jìn)行轉(zhuǎn)換和調(diào)用。

實(shí)際應(yīng)用中,都是簡化為直接聲明為指定好函數(shù)原型的指針(所以叫函數(shù)指針),這樣調(diào)用時就不需要函數(shù)原型轉(zhuǎn)換了。

帶參數(shù)的函數(shù)指針

好了,這一次我們來創(chuàng)建一個新的函數(shù)指針吧。它指向的函數(shù)仍然不返回任何值,但有了參數(shù)。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17#include
 //函數(shù)原型void

subtractAndPrint(
int

x,
int

y);
 //函數(shù)實(shí)現(xiàn)void

subtractAndPrint(
int

x,
int

y) {
    int

z = x - y;
    printf("Simon
says, the answer is: %d\n"
,
z);
} //main函數(shù)調(diào)用int

main() {
    void

(*sapPtr)(
int,
int)
= subtractAndPrint;
    (*sapPtr)(10,
2);
    sapPtr(10,
2);
}

跟之前一樣,代碼包括函數(shù)原型,函數(shù)實(shí)現(xiàn)和在main函數(shù)中通過函數(shù)指針執(zhí)行的語句。原型和實(shí)現(xiàn)中的特征標(biāo)變了,之前的sayHello函數(shù)不接受任何參數(shù),而這次的函數(shù)subtractAndPrint接受兩個int作為參數(shù)。它將兩個參數(shù)做一次減法,然后輸出到屏幕上。

  1. 在第14行,我們通過’(*sapPtr)(int, int)’創(chuàng)建了sapPtr這個函數(shù)指針,與之前的區(qū)別僅僅是用(int, int)代替了原來的空括號。而這與新函數(shù)的特征標(biāo)相符。

  2. 在第15行,解引用和執(zhí)行函數(shù)的方式與之前完全相同,只是在括號中加入了兩個參數(shù),變成了(10, 2)。

  3. 在第16行,我們用調(diào)用普通函數(shù)的方法調(diào)用了函數(shù)指針。

帶參數(shù)且有返回值的函數(shù)指針

這一次,我們把subtractAndPrint函數(shù)改成一個名為subtract的函數(shù),讓它把原本輸出到屏幕上的結(jié)果作為返回值。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20#include
 //
函數(shù)原型
int

subtract(
int

x,
int

y);
 //
函數(shù)實(shí)現(xiàn)
int

subtract(
int

x,
int

y) {
    return

x - y;
} //
main函數(shù)調(diào)用
int

main() {
  int

(*subtractPtr)(
int,
int)
= subtract;
   int

y = (*subtractPtr)(10, 2);
  printf("Subtract
gives: %d\n"
,
y);
   int

z = subtractPtr(10, 2);
  printf("Subtract
gives: %d\n"
,
z);
}

這與subtractAndPrint函數(shù)非常相似,只是subtract函數(shù)返回了一個整數(shù)而已,特征標(biāo)也理所當(dāng)然的不一樣了。

  1. 在第13行,我們通過int (*subtractPtr)(int, int)創(chuàng)建了subtractPtr這個函數(shù)指針。與上一個例子的區(qū)別只是把void換成了int來表示返回值。而這與subtract函數(shù)的特征標(biāo)相符。

  2. 在在第15行,解引用和執(zhí)行這個函數(shù)指針,除了將返回值賦值給了y以外,與調(diào)用subtractAndPrint沒有任何區(qū)別。

  3. 在第16行,我們向屏幕輸出了返回值。

  4. 18到19行,我們用調(diào)用普通函數(shù)的方法調(diào)用了函數(shù)指針,并且輸出了結(jié)果。

這跟之前沒什么兩樣,我們只是加上了返回值而已。接下來我們看看另一個稍微復(fù)雜點(diǎn)兒的例子——把函數(shù)指針作為參數(shù)傳遞給另一個函數(shù)。

把函數(shù)指針作為參數(shù)來傳遞

我們已經(jīng)了解過了函數(shù)指針聲明和執(zhí)行的各種情況,不論它是否帶參數(shù),或者是否有返回值。接下來我們利用一個函數(shù)指針來根據(jù)不同的輸入執(zhí)行不同的函數(shù)。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33#include
 //
函數(shù)原型
int

add(
int

x,
int

y);
int

subtract(
int

x,
int

y);
int

domath(
int

(*mathop)(
int,
int),
int

x,
int

y);
 //
加法 x+ y
int

add(
int

x, init y) {
    return

x + y;
} //
減法 x - y
int

subtract(
int

x,
int

y) {
    return

x - y;
} //
根據(jù)輸入執(zhí)行函數(shù)指針
int

domath(
int

(*mathop)(
int,
int),
int

x,
int

y) {
    return

(*mathop)(x, y);
} //
main函數(shù)調(diào)用
int

main() {
 //
用加法調(diào)用domath
int

a = domath(add, 10, 2);
printf("Add
gives: %d\n"
,
a);
 //
用減法調(diào)用domath
int

b = domath(subtract, 10, 2);
printf("Subtract
gives: %d\n"
,
b);
}

我們來一步一步分析。

  1. 我們有兩個特征標(biāo)相同的函數(shù),add和subtract,它們都返回一個整數(shù)并接受兩個整數(shù)作為參數(shù)。

  2. 在第六行,我們定義了函數(shù)int domath(int (*mathop)(int, int), int x, int y)。它第一個參數(shù)int
    (*mathop)(int, int)
    是一個函數(shù)指針,指向返回一個整數(shù)并接受兩個整數(shù)作為參數(shù)的函數(shù)。這就是我們之前見過的語法,沒有任何不同。它的后兩個整數(shù)參數(shù)則作為簡單的輸入。因此,這是一個接受一個函數(shù)指針和兩個整數(shù)作為參數(shù)的函數(shù)。

  3. 19到21行,domath函數(shù)將自己的后兩個整數(shù)參數(shù)傳遞給函數(shù)指針并調(diào)用它。當(dāng)然,也可以像這么調(diào)用。mathop(x, y);

  4. 27到31行出現(xiàn)了我們沒見過的代碼。我們用函數(shù)名作為參數(shù)調(diào)用了domath函數(shù)。就像我之前說過的,函數(shù)名是函數(shù)的地址,而且能代替函數(shù)指針使用。

main函數(shù)調(diào)用了兩次domath函數(shù),一次用了add,一次用了subtract,并輸出了這兩次結(jié)果。

函數(shù)名和地址

既然有約在先,那我們就討論一下函數(shù)名和地址作為結(jié)尾吧。一個函數(shù)名(或稱標(biāo)簽),被轉(zhuǎn)換成了一個指針本身。這表明在函數(shù)指針被要求當(dāng)作輸入的地方,就能夠使用函數(shù)名。這也導(dǎo)致了一些看起來很糟糕的代碼卻能夠正確的運(yùn)行。瞧瞧下面這個例子。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34#include
 //
函數(shù)原型
void

add(
char

*name,
int

x,
int

y);
 //
加法 x + y
void

add(
char

*name,
int

x,
int

y) {
    printf("%s
gives: %d\n"
,
name, x + y);
} //
main函數(shù)調(diào)用
int

main() {
     //
一些糟糕的函數(shù)指針賦值
    void

(*add1Ptr)(
char*,
int,
int)
= add;
    void

(*add2Ptr)(
char*,
int,
int)
= *add;
    void

(*add3Ptr)(
char*,
int,
int)
= &add;
    void

(*add4Ptr)(
char*,
int,
int)
= **add;
    void

(*add5Ptr)(
char*,
int,
int)
= ***add;
     //
仍然能夠正常運(yùn)行
    (*add1Ptr)("add1Ptr",
10, 2);
    (*add2Ptr)("add2Ptr",
10, 2);
    (*add3Ptr)("add3Ptr",
10, 2);
    (*add4Ptr)("add4Ptr",
10, 2);
    (*add5Ptr)("add5Ptr",
10, 2);
     //
當(dāng)然,這也能運(yùn)行
    add1Ptr("add1PtrFunc",
10, 2);
    add2Ptr("add2PtrFunc",
10, 2);
    add3Ptr("add3PtrFunc",
10, 2);
    add4Ptr("add4PtrFunc",
10, 2);
    add5Ptr("add5PtrFunc",
10, 2);
}

這是一個簡單的例子。運(yùn)行這段代碼,你會看到每個函數(shù)指針都會執(zhí)行,只是會收到一些關(guān)于字符轉(zhuǎn)換的警告。但是,這些函數(shù)指針都能正常工作。

  1. 在第15行,add作為函數(shù)名,返回這個函數(shù)的地址,它被隱式的轉(zhuǎn)換為一個函數(shù)指針。我之前提到過,在函數(shù)指針被要求當(dāng)作輸入的地方,就能夠使用函數(shù)名。

  2. 在第16行,解引用符作用于add之前,即*add,在返回在這個地址的函數(shù)。之后跟函數(shù)名一樣,它被隱式的轉(zhuǎn)換為一個函數(shù)指針。

  3. 在第17行,取地址符作用于add之前,即&add,返回這個函數(shù)的地址,之后又得到一個函數(shù)指針。

  4. 18到19行,add不斷地解引用自身,不斷返回函數(shù)名,并被轉(zhuǎn)換為函數(shù)指針。到最后,它們的結(jié)果都和函數(shù)名沒有區(qū)別。

顯然,這段代碼不是優(yōu)秀的實(shí)例代碼。我們從中收獲到了如下知識:其一,函數(shù)名會被隱式的轉(zhuǎn)換為函數(shù)指針,就像作為參數(shù)傳遞的時候,數(shù)組名被隱式的轉(zhuǎn)換為指針一樣。在函數(shù)指針被要求當(dāng)作輸入的任何地方,都能夠使用函數(shù)名。其二,解引用符*和取地址符&用在函數(shù)名之前基本上都是多余的。

感謝各位的閱讀,以上就是“C語言函數(shù)指針知識點(diǎn)總結(jié)”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對C語言函數(shù)指針知識點(diǎn)總結(jié)這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!


網(wǎng)站欄目:C語言函數(shù)指針知識點(diǎn)總結(jié)-創(chuàng)新互聯(lián)
本文來源:http://weahome.cn/article/cooddj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部