XiShiYuYuan's Blogs  
其实,我只会打游戏。。。

函数概述

函数具备3要素:1、函数名(地址)2、输入参数3、返回值

如何用指针保存函数呢?

int fun(int,int,char);

int (*p)(int,int,char);
#include <stdio.h>
int main()
{
	int (*myshow)(const char *,...);	//const char *后面不一定要写名字,这里只是声明告知
    printf("hello world!\n");
	myshow = printf;	//此时myshow和printf读内存的方式一致,就可以用指针来描述函数
	myshow("==============\n");
    return 0;
}
>>hello world!
>>==============

函数指针第一种使用方法:

#include <stdio.h>
int main()
{
	int (*myshow)(const char *,...);	//const char *后面不一定要写名字,这里只是声明告知
    printf("the printf is %p\n",printf);	//printf本身也是个地址,为0x8048320,可能会变
	myshow = (int (*)(const char *,...))0x8048320;	//把一个地址变成一个函数声明
	myshow("==============\n");
    return 0;
}
>>the printf is 0x8048320
>>==============
int (*p[7])(int,int);	//数组里存放的地址是函数地址

p[0] = fun1;
p[1] = fun2;

实参形参拷贝

#include <stdio.h>
void myswap(char buf)
{    
	printf("the buf is %x\n",buf);
}
int main ()
{
    int a = 20;
    myswap(0x1234);		//0x1234默认是int型
    return 0;
}
>>the buf is 34

对指针、数组的传参都是可以的

#include <stdio.h>
void myswap(int buf)		//p是四个字节,所以要用int接收
{
	printf ( "the buf is %x\n" , buf);
}
int main()
{
	int a = 20;
	char *p = "hello world!";

    printf("the p is %x\n",p);
    myswap(p);
	return 0;
}
>>the p is 40068b
>>the buf is 40068b
#include <stdio.h>
void myswap(int buf)		
{
	printf ( "the buf is %x\n" , buf);
}
int main()
{
	int a = 20;
	char *p = "hello world!";
	char b[10];
    printf("the b is %x\n",b);
    myswap(b);
	return 0;
}
>>the b is xxx..
>>the buf is xxx..

指针函数

主体是函数,返回类型是指针

int* f(int x, int y)

函数指针

首先f是指针,指向一个函数

int (*f)(int x, int y)

输入参数

值传递

如看到类似此种程序:

void fun(int a)		//这里是对a进行了一份拷贝,在函数中怎么变都是对副本变
{
    a = xxx;
}
int main()
{
    int a = 20;		//对这里的a没有进行任何修改,这里的a还是不变
    fun(a);
    
    printf a==?
}

地址传递

如下程序:

#include <stdio.h>
void swap (int *a,int *b)
{
	int c;
	c = *a;
	*a= *b;
    *b=C;
}
int main ()
{
	int a = 20;
    int b = 30;
    int c;
	printf ("the a is 8d,the b is %d\n",a,b);
    swap(&a, &b);		//这里传递的就是a,b的地址
	printf ("after swap, the a is %d,the b is %d\n",a,b);
}

连续空间的传递

1、数组 数组名---标签

实参:
int abc[10];

fun(abc);

形参:
void fun(int *p)    

2、结构体 结构体变量

struct abc{int a;int b;int c};
struct abc buf;

实参:
fun(&buf);
形参:
void fun(struct abc *a);

更多的是用地址传递的方式

void fun(const char *p) //只读空间,只是为了看看

int a = 12;
char buf[100];

sprintf(buf,"%d",a);
sprintf可以把a格式化转换,打印给buf,多用于格式化字符串处理
字符空间操作模板
void fun(char *p)
{
    int i = 0;
    while(p[i] != 0){
        p[i]的各种操作。。
        i++;
    }
}


实现strlen函数框架
int strlen(const char *p)
{
    int i = 0;
    /*错误处理,判断输入参数是否合法*/
    if(p==NULL){
        //return ....
    }
    /*内存处理,从头到尾逐一处理*/
    while(p[i]){
        //对p[i]的各种操作。。
        i++;
    }
}

void strcpy(char *dest,const char *src)

"" ----> 双引号一般用于初始化const char *

char buf[10] ----> 这种则初始化char *

非字符空间操作模板

结束标志:就是数据的大小、数量(B)字节

int *p unsigned char *p short *p struct abc *p 都是非字符空间操作

我们可以使用:void * 就是数据空间的标识符,可以接收任意类型的指针

void 指针作为函数形参时,可以接受任何类型指针传入

void只是个形参化,最终的操作一定要转为具体类型,如下:

void fun(void *buf,int len)
{
    unsigned char *tmp = (unsigned char *)buf;		//可以自定义一个tmp临时指针,就操作tmp
    for(i=0;i<len;i++){
        tmp[i] = xx; xx = tmp[i]  //对tmp[i]一些类操作
    }
}

int main()
{
    struct sensor_data abc;
    fun(&abc,sizeof(abc)*1)
}    

返回值

基本语法

返回值就是拷贝的过程

返回的类型:基本数据类型、指针类型,数组不能返回

函数返回值只能返回一个数据类型

返回基本数据类型

#include <stdio.h>
int fun(void)
{
	return 0x123;
}
int main()
{
	int ret;
	ret = fun();
	printf ("the ret is %x\n",ret);
    return 0;
}
>>the ret is 123
#include <stdio.h>
char fun(void)			//char类型就只返回一个字节,即23
{
	return 0x123;
}
int main()
{
	int ret;
	ret = fun();
	printf ("the ret is %x\n",ret);
    return 0;
}
>>the ret is 23
#include <stdio.h>
int fun(void)
{
    int a = 0x100;
    int *p = &a;
	return p;		//p是地址,*p不行,*p是里面的内容了
}
int main()
{
	int ret;
	ret = fun();
	printf ("the ret is %x\n",ret);
    return 0;
}
>>the ret is 48c8360c
#include <stdio.h>
int fun(void)
{
    int a = 0x100;
    int *p = &a;
    int buf[10];
	return buf;		//不能返回数组,只能返回地址
}
int main()
{
	int ret;
	ret = fun();
	printf ("the ret is %x\n",ret);
    return 0;
}
>>the ret is 0

返回连续空间类型

以下两种方式均可以使a的值发生改变:

int fun1(void); main函数中: int a=0; a = fun1();

void fun2(int *p); main函数中: int a=0; fun2(&a);

void fun2(int **p); main函数中: int *p; fun2(&p);

函数输入参数定义成*p是想改p指向的值,定义成**p是想修改p指向的地址,

指针作为空间返回的唯一数据类型

int *fun():返回类型是 * 的话,一定要考虑它的合法性,必须保证函数返回的地址所指向的空间是合法的。

不是局部变量所在的空间就行

#include <stdio.h>
char *fun(void)
{
	char buf[] = "hello world!";	
    return buf;		//buf是局部变量,函数return后buf就被回收掉了			
}
int main()
{
	char *p;
	p = fun();		//p就指向了一个消失的空间
	printf("the p is %s\n",p);
    return 0;
}
会报警告:
warning: function returns address of local variable(函数返回了一个本地变量的地址)
the p is
甚至回车符都没有打印    

另一种情况:

#include <stdio.h>
char *fun(void)
{
	return "hello world!";	//字符串常量就是个地址值,返回没问题
}
int main()
{
	char *p;
	p = fun();
	printf("the p is %s\n",p);
    return 0;
}
""在常量区,并不会因为函数的返回而消失
>>the p is hello world!

对于函数的使用:

int *fun();

int *p = fun(); //定义一个和返回类型一模一样的地址去接收即可

函数内部如何实现返回连续空间类型

1、使用static修饰:

#include <stdio.h>
char *fun(void)
{
	static char buf[] = "hello world!";	
    return buf;		//使用static修饰后,buf就在全局变量的空间,属于数据段,函数return后buf还在			
}
int main()
{
	char *p;
	p = fun();		
	printf("the p is %s\n",p);
    return 0;
}
>>the p is hello world!

2、只读区:就是直接返回字符串,但工程中意义不大

3、堆区,使用malloc申请的区域:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *fun (void)
{
    char *s = (char *)malloc(100);		//malloc一般都得加强制类型转换
	strcpy(s,"hello world");
	return s;
}
int main()
{
	char *p;
	p = fun();
	printf("the p is %s\n",p);
	free(p);			//这里释放p,因为s在函数返回后就消失了
	return 0;
}
>>the p is hello world!
posted on 2024-07-10 15:08  惜时与缘  阅读(91)  评论(0)    收藏  举报