C杂讲 函数与指针

目录

知识点1【多级指针】

知识点2【指针变量作为函数的参数】

知识点3【一维数组名作为函数的参数】

知识点4【二维数组名作为函数的参数】

知识点5【指针作为函数的返回值】

知识点6【函数名 代表的是函数的入口地址】

知识点7【函数指针 作为 函数的形参】


知识点1【多级指针】

知识点2【指针变量作为函数的参数】

1、如果想在函数内部 修改 外部变量 就需要将外部变量的地址 传递给函数(以指针变量作为函数的参数)(重要!!!!)

知识点引入:

void my_swap(int a,int b)//a=data1, b=data2
{
	int tmp=0;
	tmp = a;
	a = b;
	b = tmp;
}
void test06()
{
	int data1 = 10,data2 = 20;
	printf("data1=%d,data2=%d\n",data1,data2);
	//如果传递的是值 函数内部 是无法修改外部变量值
	my_swap(data1,data2);
	printf("data1=%d,data2=%d\n",data1,data2);
}
int main(int argc,char *argv[])
{
	test06();
	return 0;
}

上面的代码 是无法修改data1 data2的值

解决上面代码的问题 就需要将data1 data2的地址 传递到函数。

void my_swap2(int *p1,int *p2)//p1=&data1  p2=&data2
{
	int tmp;
	tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void test07()
{
	int data1 = 10,data2 = 20;
	printf("data1=%d,data2=%d\n",data1,data2);
	
	//函数内部 修改外部变量的值 需传递外部变量的地址
	my_swap2(&data1,&data2);
	printf("data1=%d,data2=%d\n",data1,data2);
}
int main(int argc,char *argv[])
{
	test07();
	return 0;
}

运行结果:

 案例:

void my_set_p(int **tmp_p)//tmp_p = &p;
{
	static int num = 100;
	//*tmp_p == p
	*tmp_p = #//p = & num;

}
void test08()
{
	int *p = NULL;

	//在函数内部 更改p的指向(在函数内部 给p赋值  就必须传递p的地址)
	my_set_p(&p);

	printf("*p = %d\n", *p);//100
	
}
int main(int argc,char *argv[])
{
	test08();
	return 0;
}

运行结果:

 

总结:函数内部修改外部变量的值 请传外部变量的地址.

外部变量为0级指针 函数的形参为1级指针

外部变量为1级指针 函数的形参为2级指针

外部变量为2级指针 函数的形参为3级指针

。。。。。。

外部变量为n-1级指针 函数的形参为n级指针

知识点3【一维数组名作为函数的参数】

1、如果函数内部想操作(读、写外部数组的元素,请将外部数组的数组名传递函数。(重要!!!)

2、一维数组作为函数的形参 会被优化成一级指针变量

案例:

//void my_input_array(int arr[5], int n)
//void my_input_array(int arr[], int n)
//一维数组 作为函数的形参会被优化成 指针变量
void my_input_array(int *arr, int n)
{
	int i=0;
	printf("B:%d\n",sizeof(arr));//4
	printf("请输入%d个int数据\n",n);
	for(i=0;i<n;i++)
	{
		scanf("%d", arr+i);
	}
	return;
}
void my_print_array(int *arr, int n)
{
	int i=0;
	for(i=0;i<n; i++)
	{
		//printf("%d ", *(arr+i));
		printf("%d ", arr[i]);

	}
	printf("\n");
}
void test09()
{
	//arr作为类型 代表的是数组的总大小
	//arr作为地址 代表的是数组的首元素地址
	int arr[5]={0};
	int n = sizeof(arr)/sizeof(arr[0]);
	
	printf("A:%d\n",sizeof(arr));//20

	//定义一个函数 给arr获取键盘输入
	my_input_array(arr, n);

	//定义一个函数 遍历数组元素
	my_print_array(arr, n);
}
int main(int argc,char *argv[])
{
	test09();
	return 0;
}

运行结果:

知识点4【二维数组名作为函数的参数】

1、如果函数内部想操作(读、写外部数组的元素,请将外部数组的数组名传递函数。(重要!!!)

2、二维数组名 作为函数的形参 会被优化成 数组指针

int arr1[5] ------> int *p;

int arr2[3][4]----->int (*p1)[4];

int arr3[3][4][5]---->int (*p2)[4][5];

int arr4[3][4][5][6]--->int (*p3)[4][5][6];

//当二维数组作为函数形参 会被优化成 数组指针
void my_print_two_array(int (*arr)[4], int row, int col)
{
	int i=0,j=0;
	printf("B:%d\n",sizeof(arr));//4
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			printf("%d ",arr[i][j]);
		}
		printf("\n");
	}
}
void test10()
{
	int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int row = sizeof(arr)/sizeof(arr[0]);//行数
	int col = sizeof(arr[0])/sizeof(arr[0][0]);//列数
	
	printf("A:%d\n",sizeof(arr));//48

	my_print_two_array(arr, row, col);

}
int main(int argc,char *argv[])
{
	test10();
	return 0;
}

运行结果:

知识点5【指针作为函数的返回值

1、函数不要返回普通局部变量的地址。

int* get_addr(void)
{
	int num = 1000;

	return &num;//不要返回普通局部变量地址
}
void test11()
{
	int *p = NULL;

	p = get_addr();

	printf("*p = %d\n", *p);//不确定
}
int main(int argc,char *argv[])
{
	test11();
	return 0;
}

2、解决上述问题:

int* get_addr(void)
{
	static int num = 1000;

	return &num;//静态变量 函数结束 不会被释放
}
void test11()
{
	int *p = NULL;

	p = get_addr();

	printf("*p = %d\n", *p);//1000
}
int main(int argc,char *argv[])
{
	test11();
	return 0;
}

知识点6【函数名 代表的是函数的入口地址

案例1:

int my_add(int a,int b)
{
	return a+b;
}
void test12()
{
	//定一个指针变量 保存该函数的入口地址
	//函数指针 本质是指针变量 保存的是函数的入口地址
	int (*p)(int,int)=NULL;
	printf("%d\n",sizeof(p));

	//my_add代表的是函数的入口地址
	printf("%p\n", my_add);//00401069

	//将函数指针 和函数名 建立关系
	p = my_add;
	printf("%p\n", p);//00401069

	//函数调用: 函数入口地址+()
	printf("%d\n", my_add(10,20));
	printf("%d\n", p(100,200));

	//对函数指针变量 取* 无意义
	(*****************printf)("hello fun\n");

	//0x00401069 
	printf("%d\n", ((int(*)(int,int))(0x00401069))(1000,2000));
}
int main(int argc,char *argv[])
{
	test12();
	return 0;
}

运行结果:

知识点7【函数指针 作为 函数的形参

案例1:

#include<stdio.h>
int my_add(int a,int b)
{
	return a+b;
}
int my_sub(int a,int b)
{
	return a-b;
}
int my_mul(int a,int b)
{
	return a*b;
}

//定义一个函数  实现上述函数的功能

int my_calc(int a,int b, int (*fun_pointer)(int,int) )
{
	return fun_pointer(a,b);
}
void test01()
{
	printf("%d\n",my_calc(10,20,my_add));
	printf("%d\n",my_calc(10,20,my_sub));
	printf("%d\n",my_calc(10,20,my_mul));

}
int main(int argc,char *argv[])
{
	test01();
	return 0;
}

运行结果:

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值