C语言简明指针教程(2)只做了一点微小的工作

指针是 C/C++的精华,如果未能很好地掌握指针,那 C/C++也基本等于没学

函数指针

  • 函数指针是指向函数的指针,指向函数的指针变量中存储的是一个函数在内存中的入口地址。
  • 冯·诺依曼体系结构强调,程序与数据共同存储在内存中,函数是子程序,当然也存储在内存中,指向存储这个函数的第一条指令的地址,称为函数的入口地址。
  • 一个函数名就是这个函数的源码在内存中的起始地址,编译器将不带()的函数名解释为该函数的入口地址。
  • 函数指针可以像一般函数一样,用于调用函数、传递参数。
  • 函数指针变量的声明:返回值类型 ( * 指针变量名) ([形参列表]);

程序示例3:

int max(int x, int y)
{
    return x > y ? x : y;
}

主函数里:
    int (* p)(int, int) = &max; // 定义函数指针,&可以省略
    int a = 8, b = 5, c = 7,  d;
    d = p(p(a, b), c); // 与直接调用函数等价
    printf("abc三个数字中最大的是: %d\n", d);

示例3运行结果:
在这里插入图片描述

  • 如果去掉* p两侧的圆括号,它声明的将是一个两个整形形参并返回整形指针的函数。

从函数返回指针

  • 必须声明一个返回指针的函数,如下所示:
int * myFunction()
{
内容
}

程序示例4:

以重写字符串连接函数strcat()为例:
char * MyStrcat(char * dstStr, char * srcStr)
{
char * pStr = dstStr;
while (*dstStr != '\0'){
// 将指针移到字符串dstStr的末尾 
dstStr++;                
}
for( ; *srcStr != '\0'; dstStr++, srcStr++){
*dstStr = *srcStr; 
} 
*dstStr = '\0';
return pStr;
}

主函数里:
char first[160] = "Hello";
char second[80] = " World!";
MyStrcat(first,second);
printf("%s\n",first);

示例4运行结果:
在这里插入图片描述

解决问题一:从函数中返回修改后的数据值

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

程序示例5:

void Fun1(int pa){
printf("Fun1 : pa = %d\n", pa ); 
pa = 2; // 改变值 
}
void Fun2(int * pa){
printf("Fun2 : *pa = %d\n", *pa ); // 传出*pa指向的变量的值
*pa = 2; // 改变指向 
}

主函数里:
int a = 1;
printf("a = %d\n",a );
Fun1(a); 
printf("a = %d\n",a );
Fun2(&a); // 传递变量a的地址 
printf("a = %d\n",a );

示例5运行结果:
在这里插入图片描述

  • 模拟按引用调用是一种常用的从函数中返回修改后的数据值的方法。(用数组名做函数实参就属于这类)

程序示例6:

void Swap(int * pa, int * pb){
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
主函数里:
int a = 1,b = 2;
printf("Before : a = %d, b = %d \n", a, b);
Swap(&a, &b);
printf("After : a = %d, b = %d \n", a, b);

示例6运行结果:
在这里插入图片描述

  • 当函数形参为指针类型而实际上却接受了一个整型的实参数据时,某些编译器会将这个整型值当做地址值,并按照这个地址值去访问内存,从而在程序运行时引发非法内存访问错误,另一些编译器会给出警告信息(不能轻视warning同志们)。

解决问题二:函数单返回值

程序示例7:

找出给定的n个数中的最大值及其对应的最小下标(下标从0开始)。(数组输入过程略)
void FindMax(int num[], int n, int * max, int * m){
    int i;
    *max = num[0];
    *m = 0;
    for(i = 0; i < n ; i++)
    {   
        if(num[i] > *max) 
        {
            *max = num[i];
            *m = i;
        }
    }
}
主函数里:
    int n = 5,max ,m ,i ;
    int num[5]={3 ,5 ,6 ,1 ,6};
    FindMax(num,n,&max,&m);
    printf("最大值%d 对应的最小下标%d",max ,m);
补:数组输入过程示例:    
int n;
int num[10]; // 一般为宏常量N
scanf("%d",&n);
for(int i = 0; i < n ; i++)
{    scanf("%d",&num[i]);}

示例7运行结果:
在这里插入图片描述

解决问题三:通用处理函数

回调函数

  • 函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。
    简单讲:回调函数是由别人的函数执行时调用你实现的函数。

程序示例8:

int a = 0;
// 回调函数
void populate_array(int * array, int n, int (* anybody)(void))
{
int i;
       for (i = 0; i < n; i++)
        array[i] = (*anybody)(); // (*anybody)()等价于直接用名字anybody()
}
// 获取值
int getValue1(void)
{a++; return a;}
int getValue2(void)
{a--; return a;} 

主函数里:
int num[10],i;
populate_array(num, 10, getValue1);
for(i = 0; i < 10; i++) {
    printf("%d ", num[i]);
}
printf("\n");
populate_array(num, 10, getValue2);
for(i = 0; i < 10; i++) {
    printf("%d ", num[i]);
}

示例8运行结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值