(1) 函式的作用就是處理資料,傳入的引數就是被加工的資料,返回值就是輸出的結果。
(2)函式名就是這個函式的入口,在記憶體中表示就是乙個函式**段的首位址,實質是乙個指標常量,所以在程式中使用函式名都是當位址來用的,用來呼叫這個函式。再理解指標函式的實質就比較簡單了。
(3) 如果乙個函式沒有傳參和返回值,也是可以的,也可以正常執行,那麼沒有返回值和形參的函式怎麼執行呢?為什麼會有這種函式呢?其實這種型別的函式在c語言中有很多。主要有兩個作用:1) 在系統初始化的時候,我們做一些系統的配置工作,這種型別的函式都是一些配置函式,不需要形參。2)我們處理一些全域性變數的資料時,會用到這種型別的函式。
我們舉個例子來說明一下什麼是輸入型引數,什麼是輸出型引數。
int
func(int
a , int
*p)int main()
執行結果:
root@ubuntu
:/mnt/hgfs/share/code/c_advance/pointer
# ./a.out
x = 10
y = 20
結論:
(1) func函式中a是輸入型引數,p是輸出型引數。
(2) 形參的傳值呼叫是輸入型引數。傳址呼叫即有可能是輸出型引數,也有可能是輸入型引數。作為輸入型引數使用時,一般會加入const關鍵字,表明是唯讀,不能修改。
今天又發現了乙個有趣的現象。事情是這樣的:我需要申請一塊記憶體空間,然後使用strcpy來拷貝乙個字串,最後printf列印,直接上**:
#include
#include
#include
void
getmemory(char
*p)int main(void
)
執行結果如下:
void@ubuntu
:/mnt/hgfs/vmshare/code/c
$ ./a.out
&str = 0xbfce7718
str = (nil
)getmemory
getmemory
: 0x81ab410
segmentation
fault (core dumped)
結果分析:報了段錯誤,為什麼呢?char *str;
是乙個區域性變數,我們傳入區域性變數然後還想要修改該區域性變數的值,這是不科學的,也是不合理的。這種雖然也是傳址呼叫,但是本質上還是傳值呼叫。說的有點繞,需要仔細體會下。 這種傳遞和上邊的傳入變數x的效果是一樣的。
那麼怎麼改呢?
兩個思路:
1、將char *str = null;
定義為全域性變數,這樣我們是把位址空間傳遞給了乙個全域性變數,這樣函式返回的時候位址空間還在。已驗證,就不貼**和執行結果了。
2、我們使用二維指標來試一下,直接上**:
#include
#include
#include
void
getmemory2(char
**p)
int main(void
)
執行結果如下:
void@ubuntu
:/mnt/hgfs/vmshare/code/c
$ ./a.out
main:
&str = 0xbff03f88
str = (nil
)getmemory2
&p = 0xbff03f70
p = 0xbff03f88
*p = 0x8c6d410
str = 0x8c6d410
&str = 0xbff03f88
hello world
滿足了我們的要求。
函式在傳參的時候,其實在棧空間又複製了乙份,比如我們定義函式:int fun(int x)
,當我們在呼叫fun(10);
的時候,其實編譯器內部操作可以看為兩步:int x ; x = 10;
,且在呼叫完成後釋放該函式申請的變數。我們再看一下這個函式:void getmemory(char *p)
,在被呼叫的時候,函式內部申請了乙個char *p
的變數,所以我們把這個變數的值是傳遞不到呼叫的函式內部的。
我們定義:void getmemory2(char **p)
,雖然它內部也定義了乙個變數char **p = &str
,我們看到被分配了位址空間:0xbff03f70
。但是*p指向了malloc申請出來的記憶體空間。所以我們的str也指向了malloc申請的記憶體空間。當函式呼叫結束,**p
被釋放,但是str指向的記憶體空間的位址確沒有改變,所以就可以正常呼叫了。換句話說,我申請了乙個二重指標指向你,然後修改了你的指向(本來指向null,後來指向malloc申請出來的空間),然後我申請的二重指標被釋放掉,但是你的指向還在。
引申:其實傳址呼叫和c++語言的引用&很相似,但又有一點不同(傳參呼叫本身也申請了變數),但是本質都是一樣的,我用多個指標變數指向同一塊記憶體,這個指標修改完被釋放,但是還有其他指標指向該記憶體,以此來達到間接修改的目的。在python中,我們也可以使用多個變數來指向同乙個物件,當沒有變數指向這個物件的時候,物件空間就會被自動**。
最後,c語言是一門博大精深的語言,需要我們認真體會。
**:
C指標之輸入型引數與輸出型引數
其實如果沒有形參列表和返回值,函式也能對資料進行加工,用全域性變數即可。全域性變數傳參最大的好處就是省略了函式傳參的開銷,所以效率要高一些 int multip5 int a void multip5 2 void int x 被乘5的變數,也就是輸入函式的變數 int y 輸出結果的變數 int ...
回型輸入和回型輸出
輸入m,n,輸出乙個m n的回型 順時針方向 矩陣,再回型 逆時針方向 輸出 對於是順時針輸入還是逆時針輸入,只需要更改初始x,y值就行。順時針 x 0,y 1 逆時針 x 1,y 0即可。至於為什麼是 1,是因為為了程式設計的方便以及避免自加後越界導致需要減回邊界 這裡使用的是迴圈較為方便,經過分...
小結 C語言的輸入和輸出
因為一直學c 不熟悉c。通過乙個例子來學c的輸入和輸出。include include include using namespace std int main int argc,char argv 1 scanf控制輸入格式,f表示輸入浮點數,必須要有 不要寫成 lf lf n r,h 雖然不知道...