函数概述

来源:互联网 发布:黄金k线软件 编辑:程序博客网 时间:2024/06/05 16:07

摘要

1/函数:一堆代码的集合,用一个标签去描述–函数名,具有输入输出功能。占有内存方式:连续一段内存。
2/运用指针调用函数
3、连续空间的函数传递,结构体参数传递

一、函数三要素

函数三要素:函数名(地址),输入参数,返回值*,一次在定义函数的时候必须将三要素告知给编译器。
1、函数名:用地址的方式访问
用指针保存函数:

    int fun(int,int char);    char (*p)(int ,int ,char);

2、定义程序、调用程序

二、函数的指针

```//运用指针调用函数int main (void){        int (*p) (int,char);//注意是(*p)        int (*p_printf)(const char *,...);        /*         1、printf的原型可以通过 man 3 printf 命令去查询;        2、第一个int与函数的返回值类型对应;        3、最后的括号是输入参数对应的类型;        4、“...”是省略参数        */        p = fun;//函数名对应的是地址        p_printf = printf;        /*        假设printf的地址为0x01234567        可以使用:p_printf=(int (*) (const char *,...))0x01234567;        */        p(13,14);        p_printf("Hello world\n");        return 0;}int fun (int a ,char b){        printf("The a is %d,the b is %d\n",a,b);        return 0;}
                ![jieguo ](http://img.blog.csdn.net/20160224215232023)运行后的结果如上图所示,发现这样赋值指针确实可以完成函数的调用。运用上述的方式,编写了一个运用指针指向函数的方式做了一个函数表,可以实现类似switch的选择函数,code如下
#include<stdio.h>void day1 (void){printf("day 1 \n");}void day2 (void){printf("day 2 \n");}void day3 (void){printf("day 3 \n");}int main (void){        int a;        void (*p[3])(void);        p[0]=day1;p[1]=day2;p[2]=day3;        for(a=0;a<3;a++)        {                p[a]();        }        return 0;}

三、函数的形参和实参

1、函数的参数的主要功能是承上启下,作为函数的承接者。
函数被调用:
函数的具体实现:函数的返回值 函数名 (接收的数据)》》》》》形参
{
XXXXX
}
函数调用“
函数名(要传递的数据)》》》》实参
实参是真实数据,实参将数据传给形参。
2、传递的形式:”copy“

如下code 实现实参交换:

#include <stdio.h>void swap(int *p_a,int *p_b ){        int tmp;        tmp=*p_a;        *p_a=*p_b;        *p_b=tmp;}int main(){        int a = 0x0a;        int b = 0x0b;        char *p = "hello world!/n";        printf(" the a is 0x0%x,the b is 0x0%x.\n",a,b);        swap(&a,&b);        printf("After swap,a is 0x0%x , the b is 0x0%x.\n",a,b);return 0;}

四、连续空间传递

连续空间的传递需要考虑地址传递
连续空间传递:数组、结构体
1、传递结构体(结构体变量)
自己编写一个分别利用结构体形参和实参传递的code

#include <stdio.h>#include <string.h>struct a{char author[100];char name[100];int sale;};void swap(int *p_a,int *p_b )//数据交换{        int tmp;        tmp=*p_a;        *p_a=*p_b;        *p_b=tmp;}void mytry(struct a sss)    //printf结构体,作为形参{printf("The book is %s,author is %s,sale : %d\n",sss.name,sss.author,sss.sale);}void change(struct a *sss) //利用指针修改实参{        sss->sale=0x0;        strcpy(sss->name,"Name_changed");}int main(){        int a = 0x0a;        int b = 0x0b;        char *p = "hello world!/n";        struct a *pbook;        struct a book={"SYT","Hello Book",999};        mytry(book);        pbook=&book;//指针赋值        printf(" the a is 0x0%x,the b is 0x0%x.\n",a,b);        swap(&a,&b);        printf("After swap,a is 0x0%x , the b is 0x0%x.\n",a,b);//      change(pbook);//指针输入        change (&book);//结构体地址输入        mytry(book);return 0;}

其code result 就不截图,很简单。

2、数组(数组名、标签)
实参 int a[20]
调用:fun( a[20])错误!!表示a的第20个元素
fun(a);
形参 : void fun (int *p)
利用数组地址传递

五、连续空间的可读性

1、字符空间
code

        void fun ( char a);//对a进行修改,值传递        void fun1 (char *b);//可能修改b,地址传递        void fun2 (const char *p);//只读

为了增加程序的可读性,通常对于可读的参量 用const进行修饰。
空间:空间的收地址和结束标致。
比如,字符串结束符 0x00

    void fun (char *p){        int i =0 ;        while(p[i]==0){            p[i]++;//操作            i++;            }

上述code就是对连续空间操作的最小结构,首先需要找到空间的起始地址,然后用查找连续空间的结束标志位。
strlen的设计

int strlen1(const char *p){int count=0;/* 错误处理 */if(*p == NULL){return 0xff;}/* 进行操作 */while (*p!=0x00){count++;p++;}return count;}

2、非字符空间
int *p,unsigned char *p,short *p;struct abc *p
需要首地址/长度

void fun(unsigned char *p ,int len){    int i;    for (i=0;i<len;i++){        p[i]+=p[i-1];        }}

形参中 常用void *p,这样就可以调用任意格式的实参。
比如 void memcpy(void dest,const void * src,siez_t n); //增加了个数的限制

int fun ( void *buf ,int len ){    unsigned char *tmp = (unsigned char *) buf;//申请缓冲指针}

六、函数返回值

函数返回值是将函数的结果或信息进行返回。
返回类型 函数名称(输入列表)
{
return XXXX;
}
1、返回基本数据类型
如下code所示:

 #include <stdio.h>int fun (void ){return 0x1234;return 0xff;}int main (void){        int a;        a=fun();        printf("a=%d\n",a);        return 0;}

返回的结果为1234
2、返回连续空间
指针作为连续空间返回的唯一类型

code :int *fun();

地址:指向的合法性
如下code:

#include <stdio.h>char * fun (void ){char buf []="hello world!";return buf;}int main (void){char *p;p=fun();printf(p);return 0;}

通过GCC编译会报如下warning:
1.c: In function ‘fun’:
1.c:6:1: warning: function returns address of local variable [enabled by default]
1.c: In function ‘main’:
1.c:13:1: warning: format not a string literal and no format arguments [-Wformat-security]
如上程序的放回值是一个临时变量的地址,在子函数返回后buf就消失了,此时main中的p再次调用时没用的。因此在函数设计过程中应该保证函数返回地址的合法性
(1)通过思考上述code的错误,考虑到因为buf为临时变量才导致了函数不能满足功能,因此尝试用 static去修饰buf。之后就能正常,满足功能了。
(2)考虑到存储空间的位置,我再次修改函数,fun函数进一步修改

code:    char * fun (void)    {        return "hello world";    }

这样就会可以完成功能实现了。

0 0