C语言-函数
参考
https://cplusplus.com/reference/clibrary/
概念
函数必须先定义后调用,所以main要放在最后
形参
形参变量只有在函数被调用时才会分配内存,调用结束后,立即释放内存,所以形参变量之后在函数内部有效
实参
实参可以是常量、变量、表达式、函数等,无论实参时何种类型的数据,在调用函数时都必须有确定的值
实参和形参在数量上、类型上,顺序上必须严格一致,可以自动进行类型转换
实参、形参可以同名,单他们之间是相互独立的,互不影响。(实参在函数外部有效,形参在函数内部有效)
赋值与参数引用机制
形参-实参相当于赋值操作
赋值
不同于下面的参数引用机制
对于数值型
赋值修改,并不会改变内存地址
inplace
操作不会改变内存地址(inplace操作也包括自增自减)
#include <stdio.h>
int main()
{
int a=1;
printf("%p\n",&a); // 000000000061FE1C
a=100;
printf("%p\n",&a); // 000000000061FE1C,地址不变
a+=100
printf("%p\n",&a); // 000000000061FE1C,地址不变
return 0;
}
参数引用机制/copy
形参与函数内的其他局部函数一样,在进入函数时被创建,退出函数时被销毁
值传递
把实际的值复制给函数的形参,不共享内存
值传递只传值 地址永远不变
#include <stdio.h>
int main()
{
int a=20;
int b=10;
int c=a;
c+=1;
printf("a %d\n",a); // 20
printf("c %d\n",c); // 21
printf("a %d\n",a); // 20
return 0;
}
进阶
想当于复制,内存地址不一样
且修改B不会影响A
#include <stdio.h>
int main()
{
int a=20;
int b=10;
int c=a;
printf("%p\n",&a); // 000000000061FE18
printf("%p\n",&c); // 000000000061FE14
c+=1;
printf("a %p\n",&a); // 000000000061FE18
printf("c %p\n",&c); // 000000000061FE14
return 0;
}
引用传递
形参为指向 实参地址 的指针,当对 形参的指向操作时,就相当于对 实参 本身进行的操作
#include <stdio.h>
#include <string.h>
// 要是返回一个指针,则要用dataType* 的方式进行定义
char *strlong(char* s1,char* s2){
if (strlen(s1)>=strlen(s2)){
return s1;
}
else{
return s2;
}
}
int main(){
char s1[30]="hello";
char s2[30]="world";
char *s3;
s3="ex";
s3=strlong(s1,s2);
printf("%s\n",s3);
return 0;
}
参数引用扩展 c/python
python的传值方式是按照c++中传指针的方式传值的,即不是引用也不是值。如果对象是可变的,那么操作是在传入对象上操作的,如果是不可变的,那么操作后相当于这个标识符指向了另一个对象
(c++传指针本质上也是值传递,只不过传的是地址值,这时候由于是值传递地址值不会被修改,但是存放在地址里的实参的值是可修改的,这时候对应于python传入对象可变的话相当于就在原对象地址上修改这个对象。如果对象本身不可变,相当于传递的是指针常量,自然不能修改这个对象)
python的赋值
a=1
a=2
# 前后两次id(a)不同
引用传递和引用符号的区别
引用传递是基于指针的
引用符号&相当于别名,并不是取地址,即共享一段内存
指针与函数
通过指针传递地址到函数,实现在函数内部操作函数外部的数据
数组、字符串、动态分配的内存,不能通过一个参数直接传递
将指针作为形参,地址作为实参进行传递
指针函数
将指针作为函数的返回值,指针就是一个地址
见引用传递
注意局部变量作为指针函数的返回值情况
函数范例
返回类型(return_type):一个函数可以返回一个值;不返回值得时候
return_type
是void
参数(parameter_list):形参列表
return_type function_name(parmeter_list)
{
...;
}
函数声明与定义
函数声明会告诉 编译器 函数名称 及 如何调用函数
函数的实际主体可以单独定义
形参的名称并不重要,只有参数的类型是必须的
// 方法1
int max(int num1,int num2)
{
...
}
// 方法2
int max(int num1,int num2); //注意是分号
// 方法3
int max(int,int)
多文件的函数调用与声明
在A文件中声明和定义,在B文件中调用,则需要在调用函数的文件B的顶部声明函数
常用函数
strcat() // 拼接两个字符串
memcpy() // 复制内存到另一个位置