C++primer學習筆記之函數

1、關於函數原型:

首先,函數的原型說明了函數在調用時候要注意的規則,比如參數的類型和數量,還有一個比較重要的就是函數的返回類型。在函數返回值的時候,他將這個值返回到指定的寄存器或者內存中,然後調用者根據這個返回值的類型才知道在內存中或者寄存器中通過偏移多少來獲取到返回值。

並且C++中的風格是不喜歡把函數的定義直接定義在main函數的前面的,所以還是需要寫函數原型的。並且在聲明函數原型的時候,函數的參數連別中可以不包括變量名,但是要包括類型。並且及時參數名和實際定義的時候不一樣也沒有關係。


函數原型在C語言中,我沒怎注意,一直都是把函數定義在調用者的前面。但是實際上函數原型在C++中有着很重要的角色。他可以幫助調用者在內存中找尋返回值,也可以幫助檢查參數列表。


C++中如過定義了一個函數的參數列表是空的話,那麼和這個參數列表裏面有void是一個意思,表明函數沒有任何參數。但是在ANSIC中這就表示現在不指出參數。如果函數是有參數的,但是調用的時候沒有給出任何參數,C++將會根據函數原型檢查出來這是個錯誤。

在ANSIC中如果函數的參數要求一個int值,但是傳遞給他的是一個double值,那麼編譯器只會在double中的前16位截取下來傳遞給函數。但是C++因爲有了原型,他會在傳遞之前將傳遞的參數轉化成原型中和參數列表相對應的類型。


通過函數原型對函數的檢查一般在函數的編譯階段進行,被稱爲靜態類型檢查。

局部變量分爲兩種,一種是在函數裏面所定義的變量,還有一種就是形參,也就是函數的參數。

 


2、函數與數組

函數名和指向數組的指針基本是相同的,都是一個數組,一斷連續內存的首地址。

但是還是有一些略微的不同,這個不同我特意寫了一個博文

http://blog.csdn.net/xr_acmer/article/details/38843671

int test[]和int *test只有在函數頭和函數的聲明部分意義纔想通,都代表一個地址。對指針加1的作用是加上了一個和指針指向元素大小相等的值。


3、指針和const

指針和const有兩種組合,第一種是將指針指向常量,防止指針改變它所指向的值,第二個就是把指針本身聲明爲一個常量,因爲指針其實也是一個值,這樣就不能改變這個指針指向的位置。

但是,這裏面有一點要注意的是,pt如果是一個指向常量的指針,但是pt指向的這個值不一定就是一個常量,指針指向的這個值是常量是相對於指向它的指針來說的,實際上是什麼樣都無所謂。總之,如果一個指針被聲明爲一個指向常量的指針的話,那麼這個值是不可能通過這個指針來修改的。

C++中可以把常量的地址複製給指向常量的指針,這樣一來,常量和這個指針都是不能改動那個數值的。但是,如果你把一個常量的地址賦值給了一個普通的指針,C++是不允許這樣的操作出現的。因爲這樣一來就證明你可以用指針改動數值,但是同時那個數值又被聲明爲const,這就很矛盾。


聲明一個指向常量的指針,不能改變的僅僅是不能通過這個指針去修改指向的那個數組,但是指針的值本身是可以修改的,因爲指針的值沒有聲明爲一個常量。所以可以隨時改變這個指針的指向,但是,即使指針指向了其他的數據,那麼依然會保持不能用這個指針修改數據的特性。


const在聲明指針的時候有兩種形式。

第一種,const int * p;  這樣就聲明瞭一個指向常量的指針。

第二種,  int * const p ; 這樣就聲明瞭一個指向整型數組的常量指針,也就是說此時不是指針指向的數據是常量而是指針本身是常量,這也就說明了,指針只能指向他被第一次賦值的那個數據,之後就再也不能改動了。但是允許這個指針去修改他所指向的數據。


關於數組和const,要注意的是,const最好只在一級間接結構上使用,超過一級則會出問題


在傳遞二維數組的指針的時候就不能再指定形參爲const,因爲這已經不是一級引用了。會出現錯誤


4、字符串和函數

字符串的表現形式在C語言中有三種

char 數組,並且最後一位要用\0

雙引號引起來的字面量。(在傳遞字符串字面量實際上傳遞的是這個字符串的地址)

一個指向char數組的指針。

在傳遞字符串的時候,不用傳遞這個字符串的長度,因爲無論是什麼形式的字符串,他的最後一個字符都是空字符。按順序查找每個字符就行。並且大多數在傳遞一個字符串的時候,如果不希望他更改,那麼要限定爲const.


5、函數指針

函數指針存儲的是函數機器碼在內存中的首地址,也就是函數名。

在聲明一個指針的時候,必須要聲明這個指針指向數據的類型,在聲明指向函數的指針的時候,必須要聲明一下函數的詳細信息。詳細信息包括函數的返回值類型還有參數列表,當然,這裏的參數列表不用寫函數名,僅僅寫出類型即可。

例如

double pam(int y);

聲明一個指向這個函數的指針

double (*p) (int)

*p就相當於pam函數,那麼p就是指向這個函數的指針。

聲明完成之後便可以把相應的函數名賦值給這個指針。賦值的成功與否,取決於這個函數指針的類型和參數列表與實際函數的返回類型和參數列表是否對應。


在聲明瞭函數指針之後,通過這個指針來調用函數有兩種方式

一種是(*pf)(),這樣的調用強調了我們正在使用指針。因爲pf是指向函數的指針,那麼*pf就是這個函數。

另一種是pf(),因爲函數名就是這個函數機器代碼的首地址,那麼指向函數的指針也是地址,所以,就可以直接把指針當作函數名來用。


在聲明函數指針的時候,其實只要記住一點,就是把函數原型中的函數名變成*指針名即可。

而在聲明一個指向函數的指針的數組的時候也很簡單,double (*p[4])(int);這就聲明瞭一個指向返回類型爲double,參數是int的函數指針的數組,數組內有4個元素。數組名爲p.


在聲明一個指向數組的指針的時候,首先要做的就是(*p)[4],把*和p進行結合,這樣的話就是一個指向有四個元素的數組的指針。相當於double (*p) (int)中 的p。所以在正式聲明一個指向函數指針數組的指針的時候可以做如下聲明。

double (*(*p)[4])(int);第一種解釋:這裏(*p)就是指向這個數組的指針,*(*p)[i]就可以訪問到數組中指向函數的指針,再加*就可以訪問到函數的返回值。

第二種解釋:p是指向數組的指針,*p就是數組,可以通過(*p)[i]來訪問數組中第i個指向函數的指針。


即使是指向函數的指針,或者是指向指針數組的指針,也有p 和&p之分

兩者雖然數值一樣,都是首地址,但是一個是數組第一個元素的地址,另一個是整個數組的首地址。

+1之後的結果截然不同,並且想訪問數組的第一個元素,對p解除一次引用,但是對&p要接觸兩次才行。 


在傳遞一個數組的時候,數組的長度可以單獨傳遞,也可以通過傳遞兩個開頭和結尾的指針來限制。

C++提供了三種形式來表示C風格的字符串,他們都是char *的類型,也就是說都是一個指針,裏面存放了字符串的首地址。使用空字符來檢測是否到了字符串的結尾處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章