首页 > 其他分享 >嵌入式软件--C语言高级 DAY 8 函数

嵌入式软件--C语言高级 DAY 8 函数

时间:2024-08-01 21:28:11浏览次数:10  
标签:return 函数 -- 作用域 C语言 int 嵌入式软件 printf 返回值

函数是C语言尤为重要的知识点,再嵌入式的学习过程中,对51和32的单片机的学习是重中之重。

一、函数的基本概念

1.介绍

函数是一种可重复使用的代码块,用于执行特定的任务或操作。

函数允许我们将代码逻辑组织成独立的单元,从而提高了代码的可读性、可维护性和重用性。

一个C程序可以由一个或多个源文件构成(C文件扩展名是“.c”),一个源文件是一个编译单位。一个源文件可以由若干个函数构成,函数之间可以相互调用。也就是说,函数是C程序基本的组成单位。

2.作用

  1. 封装功能,将一个完整的功能封装成函数,提高代码的结构化和复用性。
  2. 代码模块化,将程序按照功能拆分成若干模块单元,有助于降低复杂度。
  3. 增强可维护性,如果需要修改某项功能,只需要调整对应的函数代码。
  4. 隔离细节,通过函数调用可以隐藏实现细节,只关心输入输出。

3.分类

C语言中,从使用的角度,函数可以分类两类。

  1. 库函数,也称为标准函数,是由C系统提供的,用户不必自己定义,可直接使用它们,使用库函数,必须包含 #include 对应的头文件。
  2. 自定义函数,解决具体需求而自己定义的函数,需先定义再使用。

二、基本语法

1.结构

返回类型 函数名(参数列表)

{

    函数体语句1;

    函数体语句2;

    … 函数体语句n;

    return 返回值;

}

2.代码演示

#include <stdio.h>

// 声明函数
void func()
{
    printf("hello func\n");
}

// 实现两个数字相减
int minus(int m, int n)
{
    return m - n;
}

// 取两个数字中的最大值
int max(int a, int b)
{
    int c;
    c = a > b ? a : b;
    return c;
}

// 主函数
int main()
{
    return 0;
}

3.函数不能嵌套

C程序中的所有函数都是互相独立的,一个函数并不从属于另一个函数,即函数不能嵌套声明。

//错误演示

int func1(int a,int b) //第1个函数的定义

{  

    ...

    int func2(int c,int d)  //第2个函数的定义

    {  

       ...

    }

    ...

}

有些编译器的扩展允许函数嵌套声明,但这不是C标准的一部分,代码的可移植性可能会受到影响,强烈不建议。

三、调用函数

函数名后面加上圆括号即是函数的调用,参数写在小括号中,函数每调用一次,函数体语句都会执行一遍。

如果把参数当成是原汁原味的水果,那函数体就是把水果加工成果汁的榨汁机,返回值就是最终的果汁。

#include <stdio.h>
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    //调用函数
    printf("%d",max(10,19));
    return 0;
}

四、函数的返回值

函数调用后数能得到一个确定的值,这就是函数的返回值,返回值常常是一个计算的结果,或是用来作为判断函数执行状态的标记。

函数返回值分为以下三种情况:

  1. 无返回值类型:针对函数无返回值或明确不需返回值的情况,使用void(即空类型)表示。
  2. 有返回值类型:指明具体的类型,比如,int、float、char等。需要在函数体内与return语句搭配使用。
  3. 如果返回值类型不是void,但函数中没有return语句,则函数会返回一个不确定的值。
#include <stdio.h>

// 无返回值
void fun01()
{
    printf("fun01\n");
}

// 有明确的返回值
double fun02()
{
    return 3.14;
}

// 函数返回一个不确定的值
int fun03()
{
    10 + 20;
}

// 返回类型与return的值类型不一致,可能造成精度损失
int fun04()
{
    return 20.89;
}

int main()
{
    fun01();
    printf("%f \n", fun02());
    printf("%d \n", fun03()); // 返回一个不确定的值
    printf("%d \n", fun04()); // 返回值有精度损失

    return 0;
}

输出结果:

fun01

3.140000

10

20

五、函数的参数

函数的参数分为形参与实参:

  • 形参:在定义函数时,函数名后面括号()中声明的变量称为形式参数,简称形参。
  • 实参: 在调用函数时,函数名后面括号()中的使用的常量、变量、表达式称为实际参数,简称实参。

注意:实参的数量要与形参的数量一致,否则报错。

六、主函数

1.主函数的作用

主函数是程序的入口函数,即所有的程序一定要包含一个主函数,程序总是从这个函数开始执行,如果没有该函数,程序就无法启动。主函数中可以调用其它函数,但其它函数不能反过来调用主函数,主函数也不能调用自己。

2.主函数的返回值

C语言约定,主函数返回值0表示运行成功,如果返回其它非零整数,就表示运行失败。默认情况下,如果主函数里面省略return 0 这一行,编译器会自动加上,即 main() 的默认返回值为0。但是为了保持统一的代码风格,不建议省略。

3.主函数的参数

主函数的声明中可以带有两个参数,格式如下:

int main(int argc, char *argv[])

{

    // 函数体

}

其中,形参argc,全称是argument count,表示传给程序的参数个数,其值至少是1;而argv,全称是argument value,argv[]是一个指针数组(12.3.2小节会具体讲解),我们可以暂时将 argv 理解为是一个数组,数组的每个元素都是字符串。

这种方式可以通过命令行的方式执行源代码,并接收指定的字符串传给参数argv。

我们创建一个名为 demo.c 的源文件,代码如下:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("argc = %d\n", argc);
    // 函数体
    for (int i = 0; i < argc; i++)
    {
        printf("%s\n", argv[i]);
    }

    return 0;
}

七、函数原型

默认情况下,函数必须先声明,后使用。由于程序总是先运行main() 函数,导致所有其它函数都必须在main() 函数之前声明。

如果想将函数声明写在后面,可以在程序开头处给出函数原型。函数原型,就是提前告诉编译器,每个函数的返回类型和参数类型。其它信息都不需要,也不用包括函数体,具体的函数实现可以后面再补上。

#include <stdio.h>

// 使用函数原型进行声明
int fun(int);//可以不能定义确定的变量

// 主函数
int main()
{
    printf("%d\n", twice(100));
    return 0;
}

// 函数定义
int fun(int num)
{
    return 2 * num;
}

结果:200

八、作用域

1.概念

作用域用于确定在代码中某个标识符(如变量、标识符常量、数组等)的可见性和访问范围,它决定了在程序的哪些部分可以引用或访问该标识符。

作用域可以分为全局作用域、局部作用域、块级作用域。

同一个作用域中不能声明同名的标识符。

2.全局作用域

在函数和代码块(分支语句、循环语句等)以外定义的变量、标识符常量、数组等具有全局作用域,在程序的任何地方都可以被访问,通常称它们为全局变量、全局常量、全局数组等。

3.局部作用域

在函数内定义的变量、标识符常量、数组等具有局部作用域,只有在该函数内部才能被访问,通常称它们为局部变量、局部常量、局部数组等。需要注意的是,函数的形参也是局部变量。

4.块级作用域

块级作用域是C99标准引入的概念,在代码块(分支语句、循环语句等)中定义的变量、标识符常量、数组等具有块级作用域,只有在该代码块内部才能被访问,代码块通常具有花括号 {} 结构。

这些被称为块级变量、块级常量、块级数组等,同时也可以被称为局部变量、局部常量、局部数组,且与函数中的局部变量、局部常量、局部数组具有相同的特性。

九、课后练习题

1.定义函数,实现求两个double数字的最大值,并返回。

#include <stdio.h>
double max(double a,double b)
{
    return a>b?a:b;
}
int main()
{
    double a1,b2;
    //输入浮点数
    scanf("%lf",&a1);
    scanf("%lf",&b2);
    //调用函数
    printf("%lf",max(a1,b2));
    return 0;
}

2.定义函数,求出三个int 类型数的和,并返回。

#include <stdio.h>
//定义函数
int sum(int a,int b,int c)
{
    return a+b+c;
}
int main()
{
    int num1,num2,num3;
    //输入
    scanf("%d",&num1);
    scanf("%d",&num2);
    scanf("%d",&num3);
    //调用函数
    printf("%d",sum(num1,num2,num3));
    return 0;
}

3.定义函数,判断一个数字是否是质数。

#include <stdio.h>
int fun(int a)
{
    int count=2;
    for(int i=2;i<a;i++)//输入比这个数小的所有整数,除了1和它本身。
    {
        if(a%i==0)
        {
            count++;//只要有多余的整除因数,就可以终止
            break;
        }

    }
    if(count==2)//符合条件的返回1
    {
 return 1;
    }
   
}
int main()
{
    int num1;
    //输入
    scanf("%d",&num1);
    //调用函数
    if(fun(num1)==1)
    {
    printf("%d是质数",num1);
    }else{
        printf("%d不是质数",num1);
    }

    return 0;
}

4.函数可以没有返回值案例,编写一个函数,从终端输入一个整数打印出对应的金字塔,函数可以传入金字塔层数。

#include<stdio.h>

//函数可以没有返回值案例,编写一个函数,从终端输入一个整数(层)打印出对应的金子塔。 
//层数n是通过形参传入 
void Star(int n) { 
	int i,j,k; 
	for(i = 1; i <= n; i++) {//控制层 
	//输出空格, 使用 k 控制空格的循环 
		for (k=1; k <= n - i; k++) { 
			printf(" "); 
		}

		for(j = 1; j <= 2 * i - 1; j++) { 
			if(j == 1 || j == 2 * i - 1 || i == n) { 
				printf("*"); 
			} else { 
				printf(" "); 
			} 
		}
		printf("\n"); 
	} 
}

int main(){

	int a;
	printf("请打印金字塔层数:");
	scanf("%d",&a);
	Star(a);

}

标签:return,函数,--,作用域,C语言,int,嵌入式软件,printf,返回值
From: https://blog.csdn.net/zx18831955136/article/details/140855789

相关文章

  • 通用多级缓件组件
    背景业界第三方缓存框架一般为redis,本地缓地ehcache或guava,一般通过spring提供的restTemplate操作缓存然而这样会存在以下问题:与缓存中间件强耦合需手动整合多级缓存不支持注解数据更新时无法自动刷新缓存存在缓存穿透、缓存击穿、缓存雪崩风险日志不足改造方案基于上述问......
  • 待学习的内容
    该说不说,全部......但是,正常地学习吧。当皇冠褪去了光环,走下了神坛,让上行的阶梯一目了然。我心中的一切惘然烟消云散。对基础知识的分类:1)B级NOI+省选+——Day1DP————种类:状态压缩DP、数位DP。优化:斜率优化(凸壳)、数据结构优化DP(李超线段树)四边形不等式、凸优化(wq......
  • 学会如何安装配置开发板Atlas 200I DK A2
    前言学会如何安装配置华为云ModelArts、开发板Atlas200IDKA2。并打通一个Ascend910训练到Ascend310推理的全流程思路。在本篇章,我们首先开始训练阶段!训练阶段A.环境搭建MindSpore华为云模型训练Step1创建OBS并行文件登录华为云->控制台->左侧导航栏选择......
  • C++入门基础
    文章目录一、C++的由来1、C++的起源2、C++的版本更新二、C++的第一个程序三、命名空间1、namespace的价值2、namespace的定义3、命名空间的使用四、C++输⼊&输出五、缺省参数六、函数重载七、引用1、引用的概念和定义一、C++的由来1、C++的起源C++的起源可......
  • 枚举知识点(完结)
    枚举文章目录枚举枚举定义枚举类的实现枚举类的属性枚举类的创建创建代码常用方法枚举定义Java枚举是一个特殊类,一边表示一组常量,比如一年的4个季节,一年的12个月份,一个星期的七天,方向有东南西北等类的对象只有有限个,确定的性别:男,女枚举类的实现JDK1.5之前需要......
  • 大模型 freeze参数冻结哪些层?
    llamafactoryfreeze参数冻结哪些层AnswerLLaMAFactory中的freeze微调方法允许用户选择性地冻结模型的某些层,只对部分层进行微调。具体来说:freeze微调方法会根据用户设置的参数来决定冻结哪些层:可以设置num_layer_trainable参数来指定要训练的层数可以设置train_o......
  • InternVL 最佳实践 swift微调
    InternVL最佳实践本篇文档涉及的模型如下:internvl-chat-v1_5internvl-chat-v1_5-int8mini-internvl-chat-2b-v1_5mini-internvl-chat-4b-v1_5internvl2-1binternvl2-2binternvl2-4binternvl2-8binternvl2-26binternvl2-40binternvl2-llama3-76b以下......
  • FristiLeaks靶机
    修改靶机MAC地址080027A5A67,靶机和kali都设置成桥接,混杂改为全允许主机发现,通过Mac地址找端口扫描nmap-sV-p-192.168.7.188浏览器访问80端口:使用dirb扫描靶机目录拼接/robots.txt拼接/cola,是个提示页面回到首页,尝试将fristi作为路径进行访问......
  • sqli-labs(less-1 ~ less-8)
    1、less-11、首先输入参数我们可以看到:2、开始进行测试:输入一个单引号试试:http://127.0.0.1:8077/sql/Less-1/?id=1%27 得到报错信息:我们可以得知是字符型的sql注入3、验证一下:先输入:http://127.0.0.1:8077/sql/Less-1/?id=1%27%20and%201=1--+再输入:http:/......
  • 选择排序算法
    在Java中实现选择排序算法,首先需要理解其基本思想和步骤。选择排序是一种简单直观的排序算法,其核心思想是每次从未排序的数据元素中找到最小(或最大)的一个元素,并将其放到已排序序列的末尾。基本步骤初始化:设置一个未排序区间的起始位置为0。查找最小值:从当前未排序区间中找到......