IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】函数哪些事儿,你真的get到了吗?(2) -> 正文阅读

[C++知识库]【C语言】函数哪些事儿,你真的get到了吗?(2)

?作者:凡人编程传
?系列:C语言初阶(适合小白入门)
?说明:以凡人之笔墨,书写未来之大梦

在这里插入图片描述

?前言

今天我们接着了解函数的知识,对上一节的知识进行更深入的一个补充,让大家能够更能知道如何了解设计函数,设计自定义函数的时候应该注意哪些地方,好了,咱们直接进入正题了!

?实参和形参

在上一节中的两个自定义函数的例子都可以知道在调用函数的时候都要传递参数,在定义函数时也要创建函数参数来,接受调用函数时传递的参数。具体情况请看上一节例子【C语言】函数哪些事儿,你真的get到了吗?(1).那么我们把函数调用时,传递的参数叫做函数的实际参数(实参),把定义函数时创建的参数叫做形式参数(形参)

具体概念:

1.实参:真是传给函数的参数,叫实参。实参可以是:常量,变量,表达式,函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些传给形参。
2.形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中被实例化(分配内存单元),所以叫做形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

?函数的调用

传值调用

函数的形参和实参分别占用不同的内存块(地址),对形参的修改不会影响实参。

这也就是上一节的交换两个变量例子的第一个写法为什么没有完成交换的根本原因.
在这里插入图片描述
可以看到实参a和b与形参x和y的内存块(地址)是不同的。所以通过改变形参x和y并不能改变实参a和b。

传址调用

1.传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
2.这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

这就是上一节中交换两个变量的第二个写法能达到交换变量的原因。
在这里插入图片描述
因为我们在传实参的时候直接把实参的地址传给了形参,因而形参和实参是同一块内存块(地址)所以能够改变实参。

?练习题

设计一个判断素数的函数

素数的判断方法我有在【C语言】夏日一题 —— 如何判断素数?这一节中具体讲述,这一节我们具体讲如何设计这个函数不讲算法。不知道的老铁可以去瞅一瞅。
有的知道算法的老铁可能咔咔马上就写出来如下代码:

#include<stdio.h>
#include<math.h>
void is_prime(int k)
{
	int i = 0;
	for(i = 2; i<sqrt(k); i++)
	{
		if(k % i==0)
		{
			break;
		}
	}
	if(i>sqrt(k))
	{
		printf("%d是素数\n",k);
	}
}
int main()
{
	int n;
	printf("请输入一个数:");
	scanf("%d",&n);
	is_prime(n);
	return 0;
}

运行结果:
在这里插入图片描述

虽然说这样写的结果是对的,但是这不符合我们自定义函数的设计格式。我们这里是直接在函数内部进行了判断并且输出,但是我们这个函数的主要作用是判断一个数字是不是素数而不是输出,因为在后面工程项目中,有的程序员在调用使用你这个函数的时候只是需要这个函数来判断是不是素数,而不需要输出,如果在函数内部实现输出,那么函数就缺乏了独立性。所以我们应该把函数的结果返回一个数,让别人调用这个函数的时候,根据函数的返回值来判断是不是输出,如果需要就在主函数里面自行输出。

代码如下:

#include<stdio.h>
#inlclude<math.h>
int is_su(int a)
{
	int i = 0;
	for (i = 2; i < (int)sqrt(a); i++)
	{
		if (a % i == 0)
		{
			return 0;
		}
	}
	return 1;
int main()
{
	int n;
	printf("请输入一个数:");
	scanf("%d", &n);
	if (is_su(n) == 1)
		printf("%d是素数\n", n);
	return 0;
}

设计一个函数在一个有序数组中二分查找

同样,二分查找这个算法在【C语言】虐打循环结构练习题有详细讲解,不知道的同学可以去看看。

我们设计的这个函数只需要把那个查找到的元素的下标返回即可,而最终查找到的那个元素的下标刚好是我们中间元素下标。当然也有可能查找不到那个元素,那么这个时候就返回一个 -1,因为数组下标不可能是负数,然后根据函数的返回值来判断是否在数组中找到即可。

这里我们直接上代码来研究:

#include<stdio.h>
int half_search(int a[],int key,int s)	//这里为什么可以写成int a[]因为这里本来因果接收地址用指针int* a来接收的,而又因为数组可以写成*(a+n)来的指针形式(后续指针章节会讲),从而访问数组元素
{
	int left = 0;
	int right = s-1;
	while(left <= right)
	{
		int mid=(left+right)/2;
		if (a[mid] < key)
		{
			left = mid + 1;
		}
		else if (a[mid] > key)
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	int sz=sizeof(arr)/sizeof(arr[0]);
	int k=7;
	int t=half_search(arr,k,sz);	//这里注意,arr是数组首元素地址传参,后续数组章节会讲到
	if(t >= 0)		//如果找到了,返回的数组下标肯定是大于等于0的
	{
		printf("找到了,下标是%d\n",t);
	}
	else
	{
		printf("找不到\n");
	}
	return 0;
}

运行结果:
在这里插入图片描述

很多同学这就会说了,为啥不可以把sz直接在函数内部算出来呢。这样不是给调用函数的人更方便?我们不妨假设让sz在函数内部实现试一试。

#include<stdio.h>
int half_search(int a[],int key)	//这里为什么可以写成int a[]因为这里本来因果接收地址用指针int* a来接收的,而又因为数组可以写成*(a+n)来的指针形式(后续指针章节会讲),从而访问数组元素
{
	int sz = sizeof(a)/sizeof(a[0]);
	int left = 0;
	int right = sz-1;
	while(left <= right)
	{
		int mid=(left+right)/2;
		if (a[mid] < key)
		{
			left = mid + 1;
		}
		else if (a[mid] > key)
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8,9,10};
	int k=7;
	int t=half_search(arr,k);	//这里注意,arr是数组首元素地址传参,后续数组章节会讲到
	if(t >= 0)		//如果找到了,返回的数组下标肯定是大于等于0的
	{
		printf("找到了,下标是%d\n",t);
	}
	else
	{
		printf("找不到\n");
	}
	return 0;
}

运行结果:

在这里插入图片描述
这次你会惊奇发现,明明7在数组里面却找不到,在函数里面实现sz就找不到了,还真是有趣,我们这时候不妨调试一番。
在这里插入图片描述
可以看到sz的值和right的值居然是1和0,说明:int sz = sizeof(a)/sizeof(a[0]);的结果为1,这是为什么呢?这明明是算数组个数啊,注意这条语句是能算出数组个数但不假,但是前提是这个a的类型是整个数组,可是看清楚那个形参a的类型是int* 也就是一级指针,指针的大小是4个字节(32位机器)/或者8个字节(64位机器),这里我的平台上是32位机器,故而是4个字节,那么sz=4/4也就是1,所以我们不能把这个sz在函数里面实现(不是完全不能,后面章节的知识学了就可以了).

?结言

好了,这一节的内容就到这里,期待下一节把,希望你有收获,下节更精彩!我们下节见!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:19:47  更:2022-07-21 21:21:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 14:46:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码