函数
文章目录
1.c语言函数类型
1.1库函数
学习库函数,并学会如何使用文档来学会库函数
strcpy函数
https://legacy.cplusplus.com/reference/cstring/strcpy/?kw=strcpy
# inclue <string.h>
char arr1[20] = {0};
char arr2[] = "hello World!";
strcpy(arr1,arr2);
printf("%s\n",arr1);//输出:hello World!
memset函数
<memset - C++ Reference (cplusplus.com)>
memset
函数的头文件是string.h
(如果你在写C代码)或者cstring
(如果你在写C++代码)。
char arr[20] = "hello World!";
memset(arr,"x",5);
printf("%s",arr);//输出:xxxxx World!
char arr[20] = "hello World!";
memset(arr+6,"y",3);//偏移6个单位
printf("%s",arr);//输出:hello yyyld!
使用库函数,必须包含# include
对应的头文件
1.1.1如何学习库函数
学会查询工具的使用:
- MSDN(Microsoft Developer Network)
- cplusplus<cplusplus.com - The C++ Resources Network>
- cppreference英文版本https://en.cppreference.com/w/
- cppreference中文版本https://zh.cppreference.com/w/
1.2自定义函数
一个正常的函数:
自定义函数也需要包含这些内容。不一样的是这些都是我们自己设计的,有更大的空间。
函数的基本出现形式(比较大小):
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//函数的定义
int max(int x, int y) {//调试的时候(f11)可进入函数调试
return (x > y ? x : y);
}
int main() {
int a = 10;
int b = 20;
//函数的调用
int max1 = max(a, b);//这里进入函数调试
printf("%d", max1);
}
写个函数交换两个整型的变量
错误的示范代码:
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//形式参数,
void swap(int x,int y) {//实参a和b,传给形参xy的时候,形参将会是实参xy的一份临时拷贝
//数据是拷贝了,但空间是独立的
//对形参的修改是影响不到实参的
int z = 0;
z = x;
x = y;
y = z;
}
int main() {
int a = 10;
int b = 20;
printf("交换前:a=%d,b=%d\n", a, b);
//a和b是实参
swap(10, 20);
printf("交换后:a=%d,b=%d\n", a, b);
}
//输出:交换前:a=10,b=20
// 交换后:a=10,b=20
错误原因解析:
调用函数时,形式参数只是实参的拷贝,并非实参本参,实参和形参都是由自己独立的空间,对形参的修改影响不到实参。
如图:它们得指针变量不同,拥有不同的空间,形参调用实参时,只是对实参的值进行拷贝,之后的操作都是对形参进行的。
正确的做法是对需要交换的值直接进行修改,这里我们就想到了指针。
修改后的代码:
void swap(int* px, int* py) {//使用指针变量获取变量的值,对变量直接进行修改
int z = *px;
*px = *py;
*py = z;
}
int main() {
int a = 10;
int b = 20;
printf("交换前:a=%d,b=%d\n", a, b);
//a和b是实参
swap(&a, &b);
printf("交换后:a=%d,b=%d\n", a, b);
}
//输出:交换前:a=10,b=20
// 交换后:a=20,b=10
正确说明:
通过指针直接获取获取实参,没有开辟新的空间,就是实参本参。直接修改。
2.函数的参数
2.1实际参数(实参)
真实传给函数的参数叫做实参。
实参可以是常量、变量、表达式、函数等。
无论是何种量,在调用的时候都必须有确定的值,以便这些值传到形参。
参数为常数
int add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main() {
int a = 10;
int b = 20;
int sum = add(10, 20);
printf("%d", sum);
}
参数为变量
int add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main() {
int a = 10;
int b = 20;
int sum = add(a, b);
printf("%d", sum);
}
参数为表达式
int add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main() {
int a = 10;
int b = 20;
int sum = add(a+4, b);
printf("%d", sum);
}
参数为函数
int add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main() {
int a = 10;
int b = 20;
int sum = add(add(a,b), b);
printf("%d", sum);
}
2.2形式参数(形参)
形式参数是指函数名后面括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配到内存单元),所以叫形式参数。
形式参数当函数调用完后就自动销毁了。因此,形式参数只有在函数中有效。
3.函数的调用
3.1传值调用
函数的实参和形参分别占用不同的模块,对形参的修改不会影响实参。
3.2传址调用
传值调用是把函数外部创建的变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外面的参数建立真正的联系,也就是函数内部可以对函数外部变量直接的进行修改等操作。
4.函数的嵌套调用和链式访问
4.1函数的嵌套调用
#inclue <stdio.h>
void new_line(){
printf("hehe\n");
}
void three_line(){
int i = 0;
for(i = 0;i<3;i++){
new_line();//调用new_line函数
}
}
int main(){
three_line();//调用three_line函数
return 0;
}
函数可以嵌套调用,但是不能嵌套定义。
4.2函数的链式访问
链式访问:就是把一个函数的返回值作为另一个函数的参数
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main() {
int len = strlen("hello world");
printf("%d\n", len);
//链式访问:就是把一个函数的返回值作为另一个函数的参数
printf("%d", len);
}
小练习:
int main() {
//因为printf返回的是字符的个数,所以,第一个是正常打印的43,第二个是43的字符个数2,第三个打印的是2的字符个数1
printf("%d", printf("%d", printf("%d", 43)));
}//输出:4321
5.函数的返回值
函数不写返回值的时候,默认返回类型是int。
函数规定了返回值的类型,但是没有返回内容,有些编译器会返回最后一条指令执行的结果。
void add(void);//明确说明不需要参数,写了将会弹出警告
main函数也是有参数的
int main(int agrc,char* agrv[],char*envp[]){
//main也是有参数的
return 0;
}
6.函数的声明和定义
6.1函数的定义
函数的定义是指函数的具体实现,交代函数功能的实现。
函数的定义顺序是有要求的
系统的扫描代码的顺序是从上到下的,add函数定义在main下面,但系统扫描到add被调用时,在之前没有发现有add函数的存在。所以就会有add函数未定义的警告。但是强行运行的话也不会报错。
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main() {
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int sum = add(a, b);
printf("%d", sum);
return 0;
}
//函数的定义
int add(int x, int y) {
return x + y;
}
//弹出错误:add定义
当然,我们要把函数定义在下面也是可以的:
我们在add被调用之前进行声明操作:
//函数的声明
int add(int, int);//可不写
int add(int x, int y);//可写
6.2函数的声明
1.告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但具体是不是存在,函数声明解决不了
2.函数声明一般出现在函数的调用之前。要满足先声明后使用。
3.函数的声明一般放在头文件中。
函数的声明只需要说明:返回值类型 函数名称(参数类型)。形参可写可不写。
6.2.1函数声明在头文件中
定义函数:
# define _crt_secure_no_warnings 1
//函数的定义
int add(int x, int y) {
return (x + y);
}
在创建的头文件中声明函数:
头文件中的#pragma once的作用是,防止头文件被重复包含。
#pragma once//防止头文件被重复包含
int add(int, int);
调用函数:
使用双引号(“)引入自定义的头文件
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "add.h";//自定义的头文件使用双引号,调用
int main() {
int sum = add(20, 30);
printf("%d", sum);
return 0;
}//输出:50
7.静态库.lib
静态库的生成过程:
右击项目名称——>属性
点击属性界面后——>配置属性——>常规,将“常规属性”中的“配置类型”改为静态库
应用——>确定,然后运行项目,你会发现项目无法运行了。
此时,按照提示的地址找到一个.lib拓展名的文件。
这就是静态库,包含着函数的定义,我们将其复制到,包含头文件的目录。
尝试使用头文件和静态库完成函数的使用。具体代码如下:
# define _crt_secure_no_warnings 1
#include <stdio.h>
#include "add.h"//导入头文件
//使用#pragma comment,导入静态库
#pragma comment(lib,"22.jingtaiku.lib")
int main() {
int a = 30;
int b = 40;
int sum = add(30, 40);
printf("%d", sum);
}
//项目成功运行:输出70
全屏截图:
就完成了静态库的生成和使用。