C語言的函數

函數指針

(一)、
1、函數的地址 = &函數名(或者直接可以等於函數名,但較多用的還是&函數名)
2、函數名是指針常量,保存的是函數入口的地址
(二)、例子
int func(int num)
{
    printf("num == %d\n",num);
}
int main()
{
    func(5);
    int (*p_func)(int);  ☆
    printf("%d\n",sizeof(p_func));   △

1、函數名只有一個字節:如果將☆處修改爲:int *p_func(int),則還是一個字節,如果將 △    處修改爲sizeof(func)
還是一個字節
2、函數指針爲四個字節:如果將☆ 處修改爲int (*p_func)(int);結果爲4,將△ 修改爲sizeof(&func)結果爲4
3、函數名是什麼?是函數的入口地址      
     函數的入口地址是什麼?&函數名
    (以上兩者並不矛盾,只是兩種不同的表述)

函數指針數組

(一)、定義:
int (*p_func_array[3])(int);
(二)、初始化:
假設前面已經定義了三個調用函數func1,func2,func3
p_func_array[0] = &func1;
p_func_array[1] = &func2;
p_func_array[2] = &func3;
(三)、調用:
假設要每個函數要調用30次:
for(i = 0;i < 30;i++)
    for(j = 0;j < 30;j++)
    {
        p_func_array[j](5);
    }

回調函數

void func4(int (*p_func)(int))
{
    p_func(5);
}
int main()
{
    func4(&func1)
    func4(&func2)
    func4(&func3)
}
回調函數的好處是統一接口,增強擴展性

函數

(一)、函數可以不加形參名,比如:void swap_int(int,int);但是最好加上
(二)、函數接口(就是一個函數)的三大要素
1、函數原型
2、函數的說明文檔,其中包括函數的功能,函數形參的作用,函數的返回值
六、傳值和傳參:
例子:
#include <stdio.h>


void exchange(int *p1,int *p2)
{
    int temp;


    temp = *p1;
    *p1 = *p2;
    *p2 = temp;


}


int main()
{
    int num1;
    int num2;


    printf("Please enter num1:");
    scanf("%d",&num1);


    printf("Please enter num2:");
    scanf("%d",&num2);


    exchange(&num1,&num2);


    printf("The result is:num1 == %d,num2 == %d\n",num1,num2);


    return 0;
}


假設用的是傳值,則可假設棧空間內存分配如下:


函數的調用過程:
1、通過函數名找到函數的入口地址
2、給函數的形參分配空間
3、傳參,將實參傳給形參
4、執行函數體結構語句,交換temp,a,b
5、函數返回值返回
6、釋放棧空間
7、再打印num1,num2
傳值不能進行交換的原因是返回值執行過後,棧空間已經被釋放,根本沒有進行交換


假設用的傳地址


對x,y指向的內存空間進行操作,即對a,b直接進行操作
例子:
void add_ptr(char &ptr)
{
    ptr++;
}
int main()
{
    char *ptr = "hello world";
    add_ptr(ptr);
    printf("%s",ptr);
}


ptr並不是指針本身的地址,而是h的地址,是ptr的內容,要傳&ptr,對其地址進行操作,形參需要用指針的指針來接:**ptr


傳參總結:
1、只讀(想對操作數只使用不修改)實參變量對應空間的值傳實參變量名。
2、寫(想對操作數使用並且修改)實參變量對應空間的值傳實參變量的地址。


另外:
1、char a[] ="hello world";可以修改因爲數組分配在棧空間
2、char *a = "hello world";不可修改因爲分配在全局變量區的or段


傳出參數和傳入參數

(一)、
傳出參數:output
傳入參數:input
(二)、例子:
int continue_max(char *src,char *dest)
{
    return max;
    …………
}
int main()
{
    char *src = "dqihwdcb1234365fsdnr";
    char dest[100];
    continue_max(dest,src);
    return 0;
}
先定義一個空的字符數組dest,在經過函數填充,可帶出值,dest爲傳出參數,src爲傳入參數


返回值

(一)、爲什麼要在主函數最後加return 0?
通知系統程序正常結束,不用再做判斷


char *func()
{
    char ptr[100] = "hello world";
    return ptr;
}
int main()
{
    char *ptr = func();
    printf("%s\n",ptr);
    return 0;
}
不行,打印之前棧空間已經被釋放
可以定義:static char ptr[] = "hello world";
或者:char *ptr = "hello world";

exit函數

1、exit(1):結束整個程序並退出(括號內可以加任意值,都可以退出)
2、要看在哪一步退出?用echo$?(命令行模式下),打印當前程序結束的返回值
如果在exit(1)處結束的,則輸出1,如果在exit(2)處結束的,則輸出2,以此類推。
3、但是隻打印一二完全沒有代表性,可以這樣:
if(num == 5)
{
    printf("PASSWD ERROR!");
    exit(1);
}
4、爲了增加程序的可讀性,可以用宏定義:
#define PASSWD_ERROR 2
{
    exit(PASSWD_ERROR);
}

發佈了47 篇原創文章 · 獲贊 31 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章