从零带你认识函数(一)

简介: 从零带你认识函数

1.函数是什么?


数学中我们常见到函数的概念。但是你了解C语言中的函数吗?

维基百科中对函数的定义:子程序


1.在计算机科学中,子程序,是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。

2.一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。


2.C语言中函数的分类


在C语言中函数主要分为两种,一个是自带的库函数,还有就是我们自定义的函数。


2.1.库函数


像我们熟悉的printf()函数,scanf()函数就是C语言自带的函数,我们在使用它的时候只需要#include包含对应的头文件即可,使用printf()、scanf()函数包含stdio.h即可。

如何学习查找需要的库函数?

这里给大家分享个网站,供大家学习。

链接: www.cplusplus.com


415f9927c5da487181d1661c90f36264.png


我们在search栏里搜索memset的库函数,我们来看看结果:


ba7791648c704fb7b6c57faa27ff51ae.png


上面有函数的各个参数以及返回值等的介绍,如果英文看着难受也可以翻译成中文来学习,我们来看最下面,最下面非常直观的给出了一个例子,包括头文件的引用,以及输出结果。


2.2.自定义函数


我们要知道并不是所有的事库函数都能干。很多时候都要自己设计一个函数来完成要求,这便是自定义函数。

自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。

函数的组成:


ret_type fun_name(para1, * )
{
  statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数


我们举一个例子:


写一个函数可以找出两个整数中的最大值。


#include <stdio.h>
//get_max函数的设计
int get_max(int x, int y)
{
  return (x>y)?(x):(y);     
}
int main()
{
  int num1 = 10;
  int num2 = 20;
  int max = get_max(num1, num2);
  printf("max = %d\n", max);
  return 0;
}


再举个例子:


写一个函数可以交换两个整形变量的内容。


#include <stdio.h>
//实现成函数,但是不能完成任务
void Swap1(int x, int y)         //只改变了形参的值,实参并未发生变化。
{                                
  int tmp = 0;
  tmp = x;
  x = y;
  y = tmp;
}
//正确的版本
void Swap2(int *px, int *py)    //通过变量地址解引用来找到实参,并将其改变。
{
  int tmp = 0;
  tmp = *px;
  *px = *py;
  *py = tmp;
}
int main()
{
  int num1 = 1;
  int num2 = 2;
  Swap1(num1, num2);
  printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
  Swap2(&num1, &num2);
  printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
  return 0;
}


3.函数的参数


3.1.实际参数(实参):


真实传给函数的参数,叫实参。

实参可以是:常量、变量、表达式、函数等。

无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形

参。


3.2.形式参数(形参):


形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内

存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。


在上面代码中:Swap1 和 Swap2 函数中的参数 x,y,px,py 都是形式参数。在main函数中传给 Swap1 的 num1 ,num2 和传给 Swap2 函数的 &num1 , &num2 是实际参数。

这里我们对函数的实参和形参进行分析:


41e7e6ec65fc444abc4d6ded6b1cd525.png


这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。

形参px、py存放的是num1、num2的地址,我们可以通过解引用来找到num1、num2并进行操作。


4.函数的调用


4.1.传值调用


函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。


4.2.传址调用


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

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

作函数外部的变量。


4.3. 练习


1.写一个函数可以判断一个数是不是素数。


void f(int m)
{
  int i = 0;
  int p = 0;
  for (i = 2; i < m; i++)
  {
  if (m % i == 0)
  {
    printf("不是素数\n");
    p++;
    break;
  }
  }
  if (p == 0)
  printf("是素数\n");
}


2.写一个函数判断一年是不是闰年。


void jud(int x)
{
  if ((x % 100 != 0 && x % 4 == 0) || (x % 400 == 0))
  printf("是闰年\n");
  else
  printf("不是闰年\n");
}


3.写一个函数,实现一个整形有序数组的二分查找。

(要求:找到了就打印数字所在的下标,找不到则输出:找不到。)


#include<stdio.h>
void f(int arr[],int b)
{
  int a = 0;
  int c = 0;
  int m = 0;
  scanf("%d", &c);     //输入要查找的数
  while (a <= b)
  {
  m = (a + b) / 2;
  if (c > arr[m])
  {
    a = m + 1;
  }
  else if (c < arr[m])
  {
    b = m - 1;
  }                     //为什么要m+-1呢?
  else                  //如果要查找的数不在数组内,那a一直+1或b一直-1,直到a>b退出循环
  {
    printf("找到了,下标为:%d\n", m);
    break;
  }
  }
  if (a > b)
  printf("找不到\n");
}
int main()
{
  int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  int b = sizeof(arr) / sizeof(arr[0]) - 1;
  f(arr,b);
  return 0;
}


4.写一个函数,每调用一次这个函数,就会将 num 的值增加1。


void f(int* m)
{
  (*m)++;
}
int main()
{
  int num = 0;
  //调用函数,使得num每次增加1
  f(&num);
  f(&num);
  printf("%d", num);
  return 0;
}


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


函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。


5.1. 嵌套调用


#include <stdio.h>
void new_line()
{
  printf("hehe\n");
}
void three_line()
{
  int i = 0;
  for(i=0; i<3; i++)
  {
  new_line();    //该函数被调用三次
  }
}
int main()
{
  three_line();
  return 0;
}


函数可以嵌套调用,但是不能嵌套定义(函数里面不能定义函数)。


5.2. 链式访问


把一个函数的返回值作为另外一个函数的参数。


#include <stdio.h>
#include <string.h>
int main()
{
  char arr[20] = "hello";
  int ret = strlen(strcat(arr,"bit"));//strlen函数是将后面的字符追加到前面的字符串后面,返回值是前面字符串的起始地址                   
  printf("%d\n", ret);               //strlen函数是计算字符串的长度并返回长度大小
  return 0;
}


输出:8


#include <stdio.h>
int main()
{
  printf("%d", printf("%d", printf("%d", 43)));
  //结果是啥?
  //注:printf函数的返回值是打印在屏幕上字符的个数
  return 0;
}


输出:4321

为什么是4321呢,我们来看最右边printf,它打印43并返回2,然后中间的printf,打印2并返回1,然后左边的printf,打印1。三个打印就是4321了。


6. 函数的声明和定义


6.1 函数声明:


  1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数
  2. 声明决定不了。
  3. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
  4. 函数的声明一般要放在头文件中的


6.2 函数定义:


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


test.h的内容

放置函数的声明


#ifndef __TEST_H__
#define __TEST_H__
    //函数的声明
int Add(int x, int y);


test.c的内容

放置函数的实现


#include "test.h"      //包含头文件
    //函数Add的实现
int Add(int x, int y)
{
  return x+y;
}


在三子棋和扫雷时已经使用过这种书写形式。


相关文章
|
21天前
|
存储 人工智能 测试技术
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
141068 20
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
|
20天前
|
人工智能 运维 前端开发
基于阿里百炼的DeepSeek-R1满血版模型调用【零门槛保姆级2084小游戏开发实战】
本文介绍基于阿里百炼的DeepSeek-R1满血版模型调用,提供零门槛保姆级2048小游戏开发实战。文章分为三部分:定位与核心优势、实战部署操作指南、辅助实战开发。通过详细步骤和案例展示,帮助开发者高效利用DeepSeek-R1的强大推理能力,优化游戏逻辑与视觉效果,解决官网响应延迟问题,提升开发效率和用户体验。适合企业开发者、教育行业及多模态探索者使用。
73336 17
基于阿里百炼的DeepSeek-R1满血版模型调用【零门槛保姆级2084小游戏开发实战】
|
24天前
|
人工智能 自然语言处理 API
快速使用 DeepSeek-R1 满血版
DeepSeek是一款基于Transformer架构的先进大语言模型,以其强大的自然语言处理能力和高效的推理速度著称。近年来,DeepSeek不断迭代,从DeepSeek-V2到参数达6710亿的DeepSeek-V3,再到性能比肩GPT-4的DeepSeek-R1,每次都带来重大技术突破。其开源策略降低了AI应用门槛,推动了AI普惠化。通过阿里云百炼调用满血版API,用户可以快速部署DeepSeek,享受高效、低成本的云端服务,最快10分钟完成部署,且提供免费token,极大简化了开发流程。
191049 23
快速使用 DeepSeek-R1 满血版
|
1月前
|
人工智能 自然语言处理 Shell
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
仅用3分钟,百炼调用满血版Deepseek-r1 API,享受百万免费Token。阿里云提供零门槛、快速部署的解决方案,支持云控制台和Cloud Shell两种方式,操作简便。Deepseek-r1满血版在推理能力上表现出色,尤其擅长数学、代码和自然语言处理任务,使用过程中无卡顿,体验丝滑。结合Chatbox工具,用户可轻松掌控模型,提升工作效率。阿里云大模型服务平台百炼不仅速度快,还确保数据安全,值得信赖。
358020 62
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
|
9天前
|
人工智能 搜索推荐 数据可视化
Manus:或将成为AI Agent领域的标杆
随着人工智能技术的飞速发展,AI Agent(智能体)作为人工智能领域的重要分支,正逐渐从概念走向现实,并在各行各业展现出巨大的应用潜力。在众多AI Agent产品中,Manus以其独特的技术优势和市场表现,有望成为该领域的标杆。作为资深AI工程师,本文将深入探讨Manus的背景知识、主要业务场景、底层原理、功能的优缺点,并尝试使用Java搭建一个属于自己的Manus助手,以期为AI Agent技术的发展和应用提供参考。
11098 13
|
9天前
|
机器学习/深度学习 人工智能 测试技术
阿里云百炼已上线超强推理开源模型QwQ-32B,尺寸更小,性能比肩DeepSeek满血版
通义千问团队推出了320亿参数的QwQ-32B模型,通过大规模强化学习和多阶段训练,在数学、编程及通用能力上达到或超越了DeepSeek-R1等先进模型。QwQ-32B模型已在阿里云百炼上线,支持API调用,用户可通过官方文档了解详细使用方法。未来,团队将继续探索智能体与RL集成,推动人工通用智能的发展。
|
26天前
|
机器学习/深度学习 人工智能 自然语言处理
快来零门槛、即刻拥有 DeepSeek-R1 满血版
随着人工智能技术的发展,DeepSeek作为一款新兴推理模型,凭借强大的技术实力和广泛的应用场景崭露头角。本文基于阿里云提供的零门槛解决方案,评测DeepSeek的部署与使用。该方案支持多模态任务,涵盖文本生成、代码补全等,融合NLP、IR和ML技术,提供快速实现AI应用的便利。用户无需编码,最快5分钟、最低0元即可部署DeepSeek模型。阿里云还提供100万免费Token,适合预算有限的个人或小型团队试用。通过Chatbox客户端配置API,用户可轻松体验智能交互功能,如数学提问和代码书写等。
38730 5
|
21天前
|
人工智能 编解码 算法
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
本文介绍了通义灵码2.0 AI程序员在嵌入式开发中的实战应用。通过安装VS Code插件并登录阿里云账号,用户可切换至DeepSeek V3模型,利用其强大的代码生成能力。实战案例中,AI程序员根据自然语言描述快速生成了C语言的base64编解码算法,包括源代码、头文件、测试代码和CMake编译脚本。即使在编译错误和需求迭代的情况下,AI程序员也能迅速分析问题并修复代码,最终成功实现功能。作者认为,通义灵码2.0显著提升了开发效率,打破了编程语言限制,是AI编程从辅助工具向工程级协同开发转变的重要标志,值得开发者广泛使用。
7912 68
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
|
8天前
|
机器学习/深度学习 弹性计算 搜索推荐
真正的0代码,0脚本,0门槛,QwQ-32B一键部署!
阿里云最新发布的QwQ-32B模型通过强化学习显著提升了推理能力,在多个核心指标上达到DeepSeek-R1满血版水平,超越了DeepSeek-R1-Distill-Qwen-32B。用户可通过阿里云系统运维管理(OOS)的公共扩展功能,一键部署OpenWebUI+Ollama至ECS,轻松运行QwQ-32B模型。该方案支持本地部署和连接阿里云百炼在线模型,无需编写代码,操作简便,适合新手尝试。具体步骤包括:在阿里云控制台安装OpenWebUI扩展、选择ECS实例并创建、等待几分钟后获取URL链接,即可开始使用。此外,还提供了详细的配置指南和高级玩法介绍,帮助用户更好地利用该模型。
|
11天前
|
开发者 异构计算
高效部署通义万相Wan2.1:ComfyUI文生/图生视频实战,工作流直取!
通义万相Wan2.1开源不到一周,已登顶HuggingFace Model 和 Space 榜双榜首,在HuggingFace和ModelScope平台的累计下载量突破100万次,社区热度持续攀升!为响应小伙伴们对ComfyUI工作流运行Wan2.1的强烈需求,社区开发者整理了实战教程👇
1347 22
高效部署通义万相Wan2.1:ComfyUI文生/图生视频实战,工作流直取!