C语言的函数概念与规则你了解吗

 更新时间:2021年8月26日 16:00  点击:2340

一、函数概念

函数三要素
int fun(int,int,char){xxx}

函数名 (地址)输入参数输出参数

1.传入参数

实参: 调用时传入的具体值
形参: 函数内部接受的变量

2.返回值

返回函数处理的结果数据(另一种方式是函数外部使用址传递参数,来获得函数处理的数据)

二、函数参数

C语言函数传参,实际上就是copy的过程,参数类型的区别在于copy的多少的问题,当然类型不同可能存在丢失部分数据情况(copy不完整)

void printAddress(int a)
{
	//printAddress a地址:0xc
    printf("printAddress a地址:%p\n",a);
}
int main()
{
    int a = 12;
    //main a地址:0xc
    printf("main a地址:%p\n",a);
    printAddress(a);
    return 0;
}

void printAddress(int a)
{
	//printAddress a地址:0xffffff9b
    printf("printAddress a地址:%p\n",a);
}
int main()
{
    char a = "ABCDE";
    //main a地址:0xffffff9b
    printf("main a地址:%p\n",a);
    printAddress(a);
    return 0;
}

void printAddress(int a)
{
    //printAddress a地址:0xeccc1e18
    printf("printAddress a地址:%p\n", a);
}
int main()
{
    int a = 12;
    int *p_a;
    p_a = &a;
    //main a地址:0x7ffeeccc1e18
    printf("main a地址:%p\n", p_a);
    printAddress(p_a);
    return 0;
}

三、指针函数-函数名指针化

通过函数三要素可以得出,指针也可以表示函数
int (*p)(int,int,char){xxx} 与指针指向二维数组类似,指针必须要加(),来提高程序对他解读的优先级,而不是默认从右往左读

1.指针指向其他函数的函数名(标签)效果

int main()
{
    int (*printf2)(const char *,...);
    //HelloWOrld
    printf("HelloWOrld\n");
    printf2 = printf;
    //FFFF
    printf2("FFFF\n");
    return 0;
}

2.指针指向其他函数的地址效果

int main()
{
    int (*printf2)(const char *, ...);
    //HelloWOrld 0x7fff204b50b8
    printf("HelloWOrld %p \n", printf);
    printf2 = (int (*)(const char *, ...))0x7fff204b50b8;
    //FFFF
    printf2("FFFF\n");
    return 0;
}

3.通过二级指针,将一组函数线性化

int (*p[5])(int,int);
p[0]=func1;
p[1]=func2;
p[2]=func3;
//使用效果,可以替代switch
p[day](8,9);

四、函数值传递和址传递

值传递:void fun1(int a){...}传入数据a copy到函数中,函数中数据的修改不影响函数外被传入的数据
址传递:void func2(*a){...}传入数据地址&a copy到函数中,函数中数据的修改是在该地址上修改的,函数外被传入的数据也处在该内存地址上,所以会数据被修改

仅查看时用值传递
读写资源或节省资源时 使用址传递

五、函数连续空间的传递

连续空间传递,一般都会选择使用址传递,使用值传递浪费资源过多

1.结构体(变量)

值传递示例

struct product_t
{
    char name[20];
    int price;
};

void println(struct product_t product)
{
    strncpy(product.name, "牙刷", 20);
    product.price = 3;
    //println:牙刷
    printf("println:%s \n", product.name);
    //println:3
    printf("println:%d \n", product.price);
}
int main()
{
    struct product_t product;
    strncpy(product.name, "手机", 20);
    product.price = 3666;
    println(product);

    //main:手机
    printf("main:%s \n", product.name);
    //main:3666
    printf("main:%d \n", product.price);
    return 0;
}

址传递示例 (通过指针)

struct product_t
{
    char name[20];
    int price;
};

void println(struct product_t *product)
{
    //product[0]等价于*product此处可以替换,但是需要加()让程序优先识别,即:(*product)
    strncpy(product[0].name, "牙刷", 20);
    product[0].price = 3;
    //println:牙刷
    printf("println:%s \n", product[0].name);
    //println:3
    printf("println:%d \n", product[0].price);
}
int main()
{
    struct product_t product;
    strncpy(product.name, "手机", 20);
    product.price = 3666;
    println(&product);

    //main:牙刷
    printf("main:%s \n", product.name);
    //main:3
    printf("main:%d \n", product.price);
    return 0;
}

2.数组(标签)

数组int names[10];在定义时,编译器已经知道其首地址被names标签描述,因此数组作为形参时只需要传递数组的标签名和偏移量即可names[10]即可

数组址传递数据示例

//C语言现在优化允许使用int p[10],便于阅读 实际上效果与int *p一致,都是址传递
void println(int *p)
{
    p[0] = 77;
    //println:77
    printf("println:%d \n", p[0]);
    //println:11
    printf("println:%d \n", p[1]);
}
int main()
{
    int prices[10] = {22, 11, 55};
    println(prices);

    //main:77
    printf("main:%d \n", prices[0]);
    //main:11
    printf("main:%d \n", prices[1]);
    return 0;
}

数组址传递地址示例

//C语言现在优化允许使用int p[10],便于阅读 实际上效果与int *p一致,都是址传递
void println(int *p)
{
    p[0] = 77;
    //println:0x7ffee8964df0
    printf("println:%p \n", &p[0]);
    //println:0x7ffee8964df4
    printf("println:%p \n", &p[1]);
}
int main()
{
    int prices[10] = {22, 11, 55};
    println(prices);

    //main:0x7ffee8964df0
    printf("main:%p \n", &prices[0]);
    //main:0x7ffee8964df4
    printf("main:%p \n", &prices[1]);
    return 0;
}

如上两段代码,数组传递为址传递,数组标签名本身就是地址的标签,与指针非常相似

3.连续空间的只读

定义参数时使用const修饰指针所指的内存地址即可,如const char *p,这也是开发时默认的规范
读写函数形参:char *p;
只读函数形参:const char *p
如strncpy函数的源码:char *stpncpy(char *dst, const char *src, size_t n)

六、函数返回值

返回值与参数一样,也是copy的原理传递,可以copy值,也可以copy地址

char func1()
{
    char s = 'A';
    return s;
}
int main()
{
    char s= func1();
    //41
    printf("%X",s);
    return 0;
}

注意:指针是C语言中返回空间的唯一类型 (无法返回函数内部创建的变量地址,会被回收:异常)
int * func();

char * func1()
{
    return "HelloWorld";
}
int main()
{
    char *p= func1();
    //HelloWorld
    printf("%s",p);
    return 0;
}

工程中一般不使用上述方案(常量区存储),意义不大,通常使用静态区存储局部变量(程序结束才回收),即如下方法

char * func1()
{
    static char abc[] = "HelloWorld";
    return abc;
}
int main()
{
    char *p= func1();
    //HelloWorld
    printf("%s",p);
    return 0;
}

也可以使用堆区存储malloc()函数中创建的变量,注意使用完毕后一定要释放内存(free())

char * func1()
{
    char *s = (char *)malloc(50);
    strncpy(s,"HelloWorld",50);
    return s;
}
int main()
{
    char *p= func1();
    //HelloWorld
    printf("%s",p);
    free(p);
    return 0;
}

总结

本章主要为C语言函数概念和规则

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注猪先飞的更多内容!

[!--infotagslink--]

相关文章

  • C语言实现放烟花的程序

    这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
  • C语言中的字符(char)详细讲解

    本篇文章主要介绍C语言中char的知识,并附有代码实例,以便大家在学习的时候更好的理解,有需要的可以看一下...2020-04-25
  • php正确禁用eval函数与误区介绍

    eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
  • php中eval()函数操作数组的方法

    在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
  • Python astype(np.float)函数使用方法解析

    这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08
  • Python中的imread()函数用法说明

    这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • 详解如何将c语言文件打包成exe可执行程序

    这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
  • 金额阿拉伯数字转换为中文的自定义函数

    CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • PHP用strstr()函数阻止垃圾评论(通过判断a标记)

    strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
  • PHP函数分享之curl方式取得数据、模拟登陆、POST数据

    废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07
  • php中的foreach函数的2种用法

    Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
  • C语言中free函数的使用详解

    free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
  • C语言中计算正弦的相关函数总结

    这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下...2020-04-25
  • 详解C语言中的rename()函数和remove()函数的使用方法

    这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • C语言中求和、计算平均值、方差和标准差的实例

    这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
  • PHP函数strip_tags的一个bug浅析

    PHP 函数 strip_tags 提供了从字符串中去除 HTML 和 PHP 标记的功能,该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数...2014-05-31