C语言指针变量的赋值和做函数的参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言指针变量的赋值和做函数的参数相关的知识,希望对你有一定的参考价值。

这里面*pi=&i和px=&x是一样的么?为什么?为什么右边同样是地址,左边不相等呢?

左右两边红色标红字体,有什么区别么?还有我想问,右边下面&max为什么不能直接是max呢?如果要输入&max应该用什么方法呢?

1、指针变量的赋值,分为定义时赋值(初始化)和单独赋值,如:

int x ;
int * px=&x ; //定义时赋值,也称初始化,注意这里的*是跟随int的,即变量px是int *类型变量!  实际上的赋值语句是px=&x ;
int * py ;
py=&x ; //单独赋值,将py指向x
*py=10 ; //这里的*,是引用指针中的数据操作符,*跟随的变量必须是指针类型变量,否则会出错!  *py就是x,这里相当于x=10;

2、指针变量作为函数的参数时,子函数可以通过指针引用实参地址中的数据,达到修改实参地址中的数据。如:

#include <stdio.h>
void func( int a, int b, int *pmax )

    if ( a>b ) *pmax=a;
    else *pmax=b ;

void main()

    int a=2,b=3,max=0;
    func(a,b,&max ); //这里将变量max的地址传递到子函数,子函数中通过该地址,可以修改max的值,达到子函数结束后,max能带回运算结果的效果。
    printf("max=%d\\n", max );

参考技术A 左边的GetMax函数返回一个int类型的max
右边的GetMax函数没有返回值,函数参数是int类型的变量a,b,c和指向int类型变量的指针变量m
在调用GetMax函数时,函数参数中的max是指针变量,调用指针都要加上&表示调用的是指针地址。你这样记好了,如果遇到指针,定义函数的参数中要加*,调用函数的参数中要加&,一般都是这个规律。追问

嗯!我的意思是*pi=&i和px=&x吧,右边都是&加一个字母,为什么左边一个有*一个没有。你能解释一下*pi是指的什么,&i、px又是指的什么么?麻烦(此处是小白一只==

参考技术B 左边传的是数值。这样传过去,max这个变量自己的值不会出现变化。靠return来返回运算结果。想应的你要用返回值,也要用东西来接着他。
右边传过去的是max的地址。根据计算结果会改变max的值。直接输入地址我没试过。不建议人脑来指定内存地址,毕竟你不知道你指定的这组数字代表的内存现在装了些什么。
参考技术C 是一样的,*pi=&i只是在定义的时候把 i 的地址给 pi指针(px指向x的地址)。“为什么右边同样是地址,左边不相等呢?”这段不知道什么意思?

它们的区别是 左边是利用返回值来读函数,而右边是利用函数调用, 因为只有只有指针才能修改地址的值,要传个地址给它,调用函数中的max要取 *,获取它的值。追问

嗯!我的意思是*pi=&i和px=&x吧,右边都是&加一个字母,为什么左边一个有*一个没有。你能解释一下*pi是指的什么,&i、px又是指的什么么?麻烦(此处是小白一只==

C语言函数详解(入门到进阶)

目录

前言

一、什么是函数

二、函数的构成

三、函数的调用和声明

四、函数的参数

五、函数的递归

总结

写在后面


前言

最近帮家里的小朋友整理一些学习C语言的知识点

有整体入门基础文章——【C语言】拯救新手,半小时从零到一认识C语言基础

C语言数据类型的详解——【C语言】数据类型一文详解

变量和赋值的详解——【C语言】变量及赋值

指针和数组关系——【C语言】小妹不懂指针和数组的关系?那就安排指针数组关系详解

问了小妹她C语言还有哪些不懂得,提到了函数的应用,那么就安排函数的详解。

一、什么是函数

函数是由一系列语句组合而成的,是一组语句的封装。函数的使用可以让我们避免重复的代码编写,让我们的程序更加的模块化。

其实,咱们从接触C语言开始的时候,就已经接触了函数了。每个C语言程序至少会有一个函数,那就是main()函数。main()函数是C语言程序的入口。除了main()函数,咱们在输出的控制台信息的时候用到的printf()也是一个函数。

函数还有很多叫法,比如方法、子例程或程序,等等。

二、函数的构成

函数是由函数类型,函数名,形参列表,函数主体这几部分构成的。

函数类型 函数名(形参列表){

        函数主体;

}

  • 函数类型,决定了函数最后return的返回值类型,比如是int型函数,那么在函数体里面要用return返回int型的值,如果是char型函数,则返回char型的值。如果不需要返回值的话,则函数类型写为void
  • 函数名,是我们在调用函数时使用的,就跟变量名一个道理
  • 参数列表,咱们在调用函数时,往函数里面传入的参数,这里的参数是可有可无的,写在函数定义的参数列表的参数叫做形式参数(形参),当我们调用函数的时候,填入的叫实际参数(实参)
  • 函数主体,用花括弧{}括起来的,包含所有组成函数的语句。如果函数不是void型的,则函数主体里面要有return语句返回对应类型的值

三、函数的调用和声明

函数的调用方式:

函数名(实参列表);

这里的实参列表,可以是变量(包括普通变量和指针变量),常量,表达式,函数等。实参列表里多个实参之间用逗号【,】来隔开。当定义函数时没有形参列表,则在调用函数的时候也不用传入实参。

在咱们最熟悉的输出语句printf()就是函数的调用,例如

char str[] = "Hello Baiyu";
printf("%s\\n",str);//调用printf()函数,里面的"%s\\n",str就是实际参数
  • “%s\\n”这个是常量
  • str这个是字符串变量

下面用代码演示一下函数的定义、以及几种函数的调用形式:

#include<stdio.h>

//此处定义一个比较两个数取最大值函数
int max(int x, int y) {
    if (x > y) {
        return x;
    }
    else {
        return y;
    }
}
 
 //定义一个无返回值类型的函数,用于调用max()函数输出最大值 
void output(){
    int i_baiyu = 10;
    int i_zhh = 20;

    // 函数作为表达式的一部分
    int i_max = max(i_baiyu, i_zhh);
    int i_max2 = max(i_zhh, i_baiyu) + 100;
    
    // 函数作为自身函数的实参,同时函数也作为表达式的一部分
    int i_max3 = max(max(i_zhh, i_baiyu), i_max2);

    // 函数作为一个单独语句
    printf("i_max的值为:%d\\n", i_max);
    printf("i_max3的值为:%d\\n", i_max3);

    //函数作为调用另一个函数时的实参
    printf("函数作为调用另一个函数时的实参:%d\\n", max(max(i_zhh, i_baiyu), i_max2));
} 
 

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

由于C语言代码是从上往下依次执行的,所以对于函数的调用,咱们有两种方式

  1. 函数定义在函数调用之前,函数可以直接调用。
  2. 函数定义在函数调用之后,则需要在函数调用之前先声明被调用的函数之后再调用。

上面这两句话可能看起来有点绕。不能理解,那我们把上面这个比较大小的代码稍微调整一下,把函数定义放在main()函数后面

#include<stdio.h>

//主函数
int main() {
    output();
    return 0;
}
 
 //输出最大值 
void output(){
    int i_baiyu = 10;
    int i_zhh = 20;

    // 函数作为表达式的一部分
    int i_max = max(i_baiyu, i_zhh);
    int i_max2 = max(i_zhh, i_baiyu) + 100;
    
    // 函数作为自身函数的实参,同时函数也作为表达式的一部分
    int i_max3 = max(max(i_zhh, i_baiyu), i_max2);

    // 函数作为一个单独语句
    printf("i_max的值为:%d\\n", i_max);
    printf("i_max3的值为:%d\\n", i_max3);

    //函数作为调用另一个函数时的实参
    printf("函数作为调用另一个函数时的实参:%d\\n", max(max(i_zhh, i_baiyu), i_max2));
} 
 
//此处定义一个比较两个数取最大值函数
int max(int x, int y) {
    if (x > y) {
        return x;
    }
    else {
        return y;
    }
}

这个时候,我们执行程序可能会发现其编译时会有告警,这是因为我们的函数定义放在了函数调用之后。函数在调用的时候找不到函数的定义。

因此,我们只需要在函数调用之前,对函数进行声明,这样子的话,函数定义就可以放在程序的任意位置了。

函数的声明格式如下:

函数类型 函数名(形参列表);

我们发现,函数声明跟函数定义差不多,只是把函数定义时的函数体去掉。

修改后的代码如下:

#include<stdio.h>
void output(); //这里增加output函数的声明
int max(int x, int y);//这里增加max函数的声明

//主函数
int main() {
    output();
    return 0;
}
 
 //输出最大值 
void output(){
    int i_baiyu = 10;
    int i_zhh = 20;

    // 函数作为表达式的一部分
    int i_max = max(i_baiyu, i_zhh);
    int i_max2 = max(i_zhh, i_baiyu) + 100;
    
    // 函数作为自身函数的实参,同时函数也作为表达式的一部分
    int i_max3 = max(max(i_zhh, i_baiyu), i_max2);

    // 函数作为一个单独语句
    printf("i_max的值为:%d\\n", i_max);
    printf("i_max3的值为:%d\\n", i_max3);

    //函数作为调用另一个函数时的实参
    printf("函数作为调用另一个函数时的实参:%d\\n", max(max(i_zhh, i_baiyu), i_max2));
} 
 
//此处定义一个比较两个数取最大值函数
int max(int x, int y) {
    if (x > y) {
        return x;
    }
    else {
        return y;
    }
}

四、函数的参数

前面咱们说过,函数的形式参数列表,可以是变量(包括普通变量指针变量),常量,表达式,函数等。实参列表里多个实参之间用逗号【,】来隔开

这里单独要再强调一下,就是形参就像是函数内其他的局部变量一样。在函数调用结束之后,会进行销毁。我们在向函数传递变量时,会有两种传递参数形式。这也是为啥前面我在变量那里会强调指出有普通变量跟指针变量

  1. 传值调用:该方法会把实际参数的值复制到函数的形式参数,此时,修改函数内形式参数的值并不会影响实际参数的值
  2. 引用调用:通过指针变量来传递,形参会指向实参地址的指针,当对形参指向的值进行操作时,就相当于对实参本身进行操作

上面这样子讲可能不太好理解,还是上代码

这里咱们举一个例子就是来写一个函数,用于交换两个变量的值。

#include <stdio.h>
// 通过普通变量,进行值传递
void swap(int x, int y) {
    printf("交换前x的值为:%d,y的值为:%d\\n", x, y);
    int temp = x;
    x = y;
    y = temp;
    printf("交换后x的值为:%d,y的值为:%d\\n", x, y);
}
// 通过指针变量,进行引用传递
void swap_p(int* x, int* y) {
    printf("交换前x的值为:%d,y的值为:%d\\n", *x, *y);
    int temp = *x;
    *x = *y;
    *y = temp;
    printf("交换后x的值为:%d,y的值为:%d\\n", *x, *y);

}

int main() {
    int i_baiyu = 66;
    int i_zhh = 77;
    printf("swap交换前i_baiyu的值为:%d,i_zhh的值为:%d\\n", i_baiyu,i_zhh);
    swap(i_baiyu, i_zhh);
    printf("swap交换后i_baiyu的值为:%d,i_zhh的值为:%d\\n", i_baiyu,i_zhh);
    printf("-------------------------------------------\\n");
    printf("swap_p交换前i_baiyu的值为:%d,i_zhh的值为:%d\\n", i_baiyu, i_zhh);
    swap_p(&i_baiyu, &i_zhh);
    printf("swap_p交换后i_baiyu的值为:%d,i_zhh的值为:%d\\n", i_baiyu, i_zhh);
    return 0;
}

五、函数的递归

在开始讲函数的递归之前,给大家将一个耳熟能详的故事

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

从前有座山,山里有座庙,庙里有个老和尚给一个小和尚讲故事,讲什么呢?老和尚说

......

在C语言中,当函数直接或者间接调用函数本身,就叫做函数的递归。

在使用函数递归的时候,我们要注意设置好一个从函数退出的条件,否则就会进入一个死循环,就像老和尚给小和尚讲故事一样,是无限循环的。

函数的递归,这样子讲可能不太容易懂,下面举几个例子,让大家一起熟悉一下

通过递归求n的阶乘

我们从数学公式可知

n! = n *(n-1)!

#include <stdio.h>

double factorial(unsigned int i)
{
    if (i <= 1)//这里就是结束递归的判断条件
    {
        return 1;
    }
    return i * factorial(i - 1);
}
int  main()
{
    int i_baiyu = 6;// 这里我们计算6的阶乘。
    printf("%d 的阶乘为 %f\\n", i_baiyu, factorial(i_baiyu));
    return 0;
}

 6!= 6 * 5 * 4 * 3 * 2 * 1 = 720

总结

本文讲述了C语言函数的定义、基本使用,和函数的递归。从零到一带各位同学熟悉C语言中函数的使用。

写在后面

如果觉得有用的话,麻烦动动各位发财的小手指,给个一键三连支持一下攻城狮白玉并把本文分享给更多的小伙伴。你的简单支持,我的无限创作动力

如果有想看的内容,也可以在博文底部评论,我会整理出来给到大家~

以上是关于C语言指针变量的赋值和做函数的参数的主要内容,如果未能解决你的问题,请参考以下文章

c语言如何给结构体指针赋值?

c语言如何给指针参数赋值为null?

C 语言指针间接赋值 ( 指针作为 函数参数 的意义 | 间接赋值 代码示例 )

在c语言中整形变量的指针能否赋值给整形变量?

C 语言指针间接赋值 ( 间接赋值三要素 | 间接赋值 使用的三种场景 )

在C语言中能否直接给指针指向的数据赋值?为啥?