关于函数的初学【2】函数的调用与写法

函数的调用分为两种方式

传值调用

传值调用的特点是形参和实参分别占有不同的内存块,对形参的修改不会影响实参

传址调用

1.传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数

2.这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量

关于这两种函数调用方式最重要的区分就是

当我们想在函数块中将函数块外的量变化时时,我们就要用传址调用

关于素数练习:
 

#include <stdio.h>
#include <math.h>
int add(int x)
{
	int a = sqrt(x);
	int k = 2;
	int z = 1;
	int m = x % k;
	for (k = 2; k <= a; k++)
	{
		if (m == 0)
		{
			break;
		}	
	}
	if (m == 0)
		return 0;
	else
		return z;
}
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
		if (add(i) == 1)
			printf("%d ",i);
	return 0;
}

上面这一段代码是可以优化的

优化结果如下:

#include <stdio.h>
#include <math.h>
int add(int x)
{
	int a = sqrt(x);
	int k = 2;
	int m = x % k;
	for (k = 2; k <= a; k++)
	{
		if (m == 0)
		{
			return 0;
		}	
	}
	return 1 ;
}
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
		if (add(i) == 1)
			printf("%d ",i);
	return 0;
}

本次优化最重要的一点是return 0;的设置

(ps:函数如果有返回类型的话就一定要有返回值,运用二分查找的前提是有序数组,整型相除的话结果自动向下取整,f10逐语句,f11逐过程(要从语句转换为函数时就按f11,只有语句时只按f10即可))

在代码块中如果return 0; 语句能够被执行的话,那么就会直接将0返回给函数,函数的运行结束!

return 0;就是直接将0返回给函数,return 1;就是直接将 1返回给函数

知道了这个后break就显得多余了。

在编程中,先去考虑函数用来干什么,然后再去考虑函数的功能该怎么去实现

关于数组在函数传参时的一些问题

#include <stdio.h>
int add(int arr[]) 
//由于数组的特殊性,当我们在这里建立一个数组类型的形式参数 - int arr[] 时,我们其实是在建立一个指针变量,即arr[]其实是一个指针变量
//而这个指针变量就是用来存放数组实参传过来的地址的
//函数内只能够获取外部数组中的第一个元素的地址,不满足用sizeof来求数组元素个数的条件
//运用sizeof的条件是知道数组所有元素字符长度之和,即总字符长度
{
    //....算法实现
}
int main()
{
    int arr[]={1,2,3};
    add(arr); 
//数组作为参数传给函数时,传过去的并不是整个数组
//而是数组中存放第一个元素的存储空间的地址!
    return 0;
}

//综上我们可以得知,在函数的内部是无法求得外部数组的元素的个数的,外部数组的元素个数只能在外部求好后再作为实参传给函数
//以及函数内部无法求得外部数组的元素个数,要想在函数中得到外部数组的元素的个数的话,只能在外部求得外部数组的元素个数后,再将个数作为实参传给函数

关于指针变量++的问题,设p为指针变量

有以下两种形式

*p++ 和 (*p)++

其中左边的那种形式的逻辑是先对p++,然后再解引用

而右边的逻辑则是对p解引用后的结果++

函数的嵌套调用和链式访问

函数和函数之间是可以进行有机的组合的 

嵌套调用 - 其实就是在一个函数中可以调用另一个函数

链式访问:把一个函数的返回值作为另一个函数的参数

#include <stdio.h>
#include <string.h>
int main()
{
    int len = strlen("abc"); 
//这一段的代码意思其实就是将strlen函数的返回值(字符串”abc“的长度)存到整型变量len中
//然后我们再打印len
//有没有什么办法可以一步就实现上面这两个步骤呢?
//答案是有的,那就是函数的链式访问
    printf("%d",len);
    printf("%d",strlen("abc"));
//我们可以直接将strlen函数的返回值 strlen("abc")作为printf函数的参数来使用,而不需要再创建一个len变量来存储返回值
//strlen("abc")先作为传参的入口,参数抵达函数,函数处理完参数后返回数值,而这个返回数值又被存进了strlen"abc"中
    return 0;
}

如:

int main()
{
    printf("%d",printf("%d",printf("%d",43)));
//首先我们通过查函数库知道printf()函数的返回值是它打印的字符的个数(整型类型)
//其次函数的逻辑是先被调用实现功能,然后再返回功能实现后的返回值
//最后这一段代码的逻辑如下:
//从左往右,如果我们想实现第一个printf的功能,必须知道它的参数,然后依次类推我们需要知道最后一个printf的返回值才能实现第一个printf
//于是我们先调用最后一个printf -- 1.实现功能 - 打印数字43 2.获得实现功能后的返回值 - 打印的字符个数2,然后是倒数第二个printf,一样先打印再获得参数,然后再继续
//最终我们得到的结果就是 4321
    return 0;
}

关于printf函数的一点补充:

printf(" 这是printf函数里的内容 "  ,  这是pritf函数外的内容);

printf函数里的内容即双引号中的内容可以直接打印而不需要类型声明

但是当我们想在双引号中打印printf函数外的内容时,我们要在我们想打印位置声明这个想要打印的东西的类型%d %s .... ,然后在双引号外 逗号+想打印的函数外的内容

函数的声明和定义

函数声明:

1.告诉编译器有一个函数叫什么,参数是是什么,返回类型是什么,但是这个函数具体是否存在,无关紧要。也就是说函数的声明只是在说我有这么一个函数,但这个函数是否真的存在并不确定

如 int add (int x , int y)

2.函数的声明一般出现在函数的使用之前,要满足先声明后使用

3.函数的声明一般要放在头文件中

函数的定义:

如 int add(int x , int y);

{

        //算法实现

}

1.如果我们声明的函数具有确切的定义,那么我们声明的这个函数是存在的,否则不存

2.函数的定义是指函数的具体实现,交代函数的功能实现。

在实际开发中我们并不是将所有的函数都直接写在同一个文件中

我们往往将函数拆分成由两部分组成的功能模块 ,这两部分就是函数声明和函数定义

函数声明往往被放在 .h 文件即头文件中,然后函数的定义即函数的实现被放在一个单独的.c文件中

这样一个.h文件和.c文件的组合就是函数功能模块,当我们想要在一个.c文件中(非函数定义所在的.c文件)使用这个函数时,我么只需要引用这个函数对应的头文件即可直接使用函数

比如库函数:

#include <stdio.h> 引入对应的头文件,引入后即可直接使用函数

int mian

{

printf("abc");  函数名(要传递的实参)这样即可直接使用函数

}

(ps:引用库函数时:#include <头文件名>  ,引用我们自己创建的函数时: #include "头文件名",库函数的头文件引用用< >,自己创建的头文件的引用是” “

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值