指针

本文详细介绍了C语言中的指针概念,包括变量的内存地址、指针变量的定义与初始化、间接寻址运算符等内容,并探讨了按值调用与模拟按引用调用的区别。此外,还介绍了如何使用指针变量作为函数参数实现值的修改,并展示了函数指针的应用实例。
摘要由CSDN通过智能技术生成

指针

一、变量的内存地址

先明确两个概念:
变量的地址:变量在内存中所占空间的首地址;
变量的值:变量在存储空间的存放的地址;

二指针变量的定义和初始化

1、指针变量的定义:

类型关键字 *指针变量名

int *pa;
int *pa, *pb;

为了避免忘记给指针初始化带来的潜在危险,习惯上在定义指针变量的时候,将其初始化为NULL:

int *pa = NULL;

2、指针的初始化

指针变量只能指向同一基类型的变量

int a = 10;
int *pa;
pa = &a;
int a = 10;
int *pa = &a;

三、间接寻址运算符

通过变量名和变量的地址存取变量的内容的访问方式,叫直接寻址;
通过指针变量存取他所指向的变量额度访问方式,叫间接寻址;
获取变量地址需要取址操作符‘&’;
指针运算符或者是间接寻址运算符‘*’;

#include "stdio.h"

int main()
{
    int a = 0;
    float b = 3.0;
    char c = 'a';
    int *pa = &a;
    float *pb = &b;
    char *pc = &c;
    printf("a = %d, a = %d, *a = %d, *a = %d", a, *pa, &a, pa); 
}

结果是:a = 0, a = 0, *a = 10485300, *a = 10485300
指针使用的准侧就是:

永远不要使用未初始化的指针变量;

四、按值调用与模拟按引用调用

普通变量做函数参数其实就是按值调用。

下面看一组代码:

#include "stdio.h"

void fun(int a)
{
    printf("a = %d\n", a);
    a = 2;
}

int main()
{
    int a;
    printf("Please input a number:\n");
    scanf("%d", &a);
    fun(a);
    printf("a = %d", a);
    return 0;

}

结果是:
Please input a number:
5(输入)
a = 5(输出)
a = 5

上面这段代码说明普通变量是按值引用的,我们更改函数的形参并未影响到实参的变化,这是因为你传给函数形参的值只是调用函数中实参的副本而已.

通过向函数传递某个值的地址值可以在被调函数中更改实参的值,因为相当于模拟了c++中的按引用调用,所以这里称为模拟按引用调用

下面我们来简单的更改一下代码:

#include "stdio.h"

void fun(int *a)
{
    printf("a = %d\n", *a);
    *a = 2;
}

int main()
{
    int a;
    printf("Please input a number:\n");
    scanf("%d", &a);
    fun(&a);    //向函数传递地址值;
    printf("a = %d", a);
    return 0;

}

结果是:
Please input a number:
5(输入)
a = 5(输出)
a = 2
看完模拟按引用调用的第一个作用:在另一个函数中更改实参的值之后,我们来看他的第二个作用:

#include "stdio.h"

int fun(int a)
{
    printf("a = %d\n", a);
    a = 2;
    return a;
}

int main()
{
    int argc = 1;
    printf("a = %d\n", argc);
    argc = fun(argc);   
    printf("a = %d\n", argc);
    return 0;
}

结果是:
a = 1
a = 1
a = 2
没有想到吧,运用return 我们可以达到像上面一样的效果;所以呢应用返回值,我们也可以在被调函数中修改实参的值;

好吧,言归正传我们要说的是第二个用法,就是利用模拟按引用调用从函数中返回多个值

#include "stdio.h"

void Swap(int *a, int *b);

int main()
{
    int a;
    int b;
    printf("please input a and b:\n");
    scanf("%d%d", &a, &b);
    Swap(&a, &b);   //向函数传递地址值;
    printf("a = %d\nb = %d\n", a, b);
    return 0;
}

void Swap(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

结果是:
please input a and b:
1 5(输入)
a = 5(输出)
b = 1

五、用指针变量做函数地址值

#include "stdio.h"
#define N 40

void findMax(int *pa, long *pb, int n, int *maxscore, long *maxnum);

int main()
{
    int score[N];
    int maxScore;
    int i, n;
    long num[N], maxNum;
    printf("How many students:\n");
    scanf("%d", &n);
    printf("Please input studentID and score:\n");
    for(i=0;i<n;i++)
    {
        scanf("%ld%d", &num[i], &score[i]);
    }
    findMax(score,num, n, &maxScore, &maxNum);  //将数组和变量的地址传给被调函数;
    printf("maxNum = %ld\nmaxScore = %d\n", maxNum, maxScore);
    return 0;
}

void findMax(int *pa, long *pb, int n, int *maxscore, long *maxnum) //定义形参指针
{
    int i,score;
    *maxscore = *pa;
    for(i=0;i<n;i++)
    {
        if(*maxscore < *pa)
        {
            *maxscore = *pa;
            *maxnum = *pb;
        }
        pa++;
        pb++;
    }
} 

结果是:
How many students:
4
Please input studentID and score:
121212 90
131313 91
141414 92
151515 93
maxNum = 151515
maxScore = 93
这段代码可能有点超出本篇的范围了,如果看不懂请参见数组与指针(一)和数组与指针(二);

五、函数指针

看了这么多,大家应该也累了,所以我们上段代码,把这个solve了!

#include "stdio.h"

int add(int a, int b)
{
    return a+b;
}

int sub(int a, int b)
{
    return a-b;
}

int caculate(int a, int b, int (*calculate)(int a, int b))
{
    int result;
    result = (*calculate)(a, b);
    return result;  
}

int main()
{
    int a, b;
    int result_1, result_2;
    printf("Please input a and b:\n");
    scanf("%d%d", &a, &b);
    result_1 = caculate(a, b, add);
    result_2 = caculate(a, b, sub);
    printf("a + b = %d\n", result_1);
    printf("a - b = %d\n", result_2);
    return 0;
}

结果是:
Please input a and b:
1 5(输入)
a + b = 6(输出)
a - b = -4


大家也看到了,函数指针就是这样神奇!

函数指针就是指向函数指针,在前面的知识中我们知道,一个数组名就是存储数组第一个元素的内存地址,同样的道理,一个函数名就是这个函数代码在内存中的起始地址;上面的代码中,我想你也知道函数指针的价值:把一些重复性的工作放在母函数中,把核心的子函数单独放出来,其核心价值就是减少重复代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值