函数名(参数列表)(可以省略参数名,但是不可以省略参数的数据类型)
以下是一个简单求和函数的代码。
#include<stdio.h>
int add(int ,int); //此处函数声明省略了参数名 但是需要保留擦参数的数据类型
int main()
{
int m,n;
scanf("%d",&m);
scanf("%d",&n);
printf("m + n = %d\n",add(m,n));
}
int add(int a ,int b)
{
int temp = 0;
temp = a+b;
return temp;
}
(2)函数定义:
存储类型数据类型 函数名(形式参数列表)
{
函数体;
返回值;
}
函数名:见名知意
形参:实现功能所需要的参数,需要调用者自己传
返回值:如果没有返回值,可以省略,数据类型void
(3)调用函数:
函数名(实际参数列表)
注意:
1、 实参的数据类型和个数和形参保持一致
2、 实参可以是常量、变量、表达式、但是必须是一个确定的值
3 、实参和形参是俩个独立的内存空间
4 、传参实际上是将实参的值拷贝给形参
在函数中,我们常常会使用实际参数和形式参数。当我们调用形式参数的时候需要注意一些细节的问题,当我们定义了一个形式参数的时候,会重新给我们分配一个新的空间。
如下代码是一个数值交换的函数,我们可以清晰的了解到实际参数和形式参数的不同。
此处我们看见,我们想要的结果并没有出现,a和b的值并没有发生交换,但是在函数体内,形式参数m和n的数值确实进行了交换。
通过打印地址,我们可以发现形参和实参的地址是不一样的,所以,我们的函数只进行了形参的交换,并没有进行实参的交换。如果我们想让这个函数成功实现功能,我们需要加上取地址符。
加上取地址符后,我们发现实参不仅传递了值,同时也将地址进行了传递,这样在同一个地址进行操作时实参就可以实现数值的交换。
5 、形参是局部变量,在函数调用时被定义,函数使用完毕后,释放空间
2、递归函数
程序调用自身的编程技巧称为递归( recursion);
调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
//利用递归升序输出1 - 5 的整数
void dg(int n)
{
if(n > 0)
{
dg(n - 1);
printf("%d\r\n",n);
}
}
int main()
{
int i = 5;
dg(i);
}
此处递归的回溯,类似于栈,回溯的过程相当于从栈顶到栈底的输出。
3、指针
指针:指针是一种变量 是一种保存地址的变量
地址:内存分配的最小单位是字节,每一个字节都有着属于自己的编号,这个编号就叫做地址
地址的本质:内存的单元的编号
指针:指针就是地址 内存的单元的编号
指针的定义:存储类型 数据类型* 指针变量名(例如:Int *p)
数据类型的分辨:数据类型:指针所指方向的数据类型(去掉*和p)
指针大小:
32操作系统 所有的指针占4个字节
64操作系统,所有的指针占8个字节
int main()
{
int *p;
char *q;
printf("%d\n",sizeof(int *));
printf("%d\n",sizeof(char *));
} //和操作系统的位数有关系
指针的赋值:
在对指针赋值时,一定要注意数据类型匹配
1、空指针:
这就是一个空指针,此时我们给他进行赋值操作,但是并没有输出a的值。
空指针不会指向任何地方,它不是任何对象或函数的地址。
在源码中用来表示空指针的常量是整数0,NULL使指针指向0,大多数系统中都将0作为不被使用的地址
0地址禁止操作(所以以上代码不会对指针a进行赋值)。
一般用用空指针NULL来初始化指针变量。
2、野指针:
野指针就是指向的内存地址是未知的(随机的,不正确的,没有明确限制的)。
容易产生野指针的地方:
1、没有给指针初始化;
2、指针越界访问;
3、指针释放后未置空;
当我们书写程序时,应该极力的避免上面这些情况。
以下是规范书写:
使用指针时先进行初始化;
#include<stdio.h>
int main()
{
int s = 4;
int *p = NULL; //指针初始化
p = &s; //将S的地址赋值给P
printf("%d\r\n",*p);//输出的值就是S的值
}
注意下标的大小,避免指针越界;
#include<stdio.h>
int main()
{
int num[5] = {1,2,3,4,5};
int *p = num;
for(int i = 0 ;i < 5 ;i++) //该处注意下标的大小 不要越界
{
printf("%d,%d,%p\r\n",*p,i,p);
*(p++) = num[i];
}
*p = 50;
printf("%d\r\n",*p);
return 0;
}
当下标没有越界时 此时的指针不是野指针,我们可以对其进行赋值操作。
如果我们下标越界时,此时指针变成野指针,不能进行赋值操作。
如下图:
这是正确的操作,指针此时没有发生越界,可以进行赋值操作。
下图是指针发生越界,此时指针变成野指针,所指位置随机,不能进行赋值操作。