C语言学习——指针精华(2)

在这里插入图片描述
在这里插入图片描述

字符指针作函数参数

[用函数调用实现字符串的复制]
⑴用字符数组作参数

#include <stdio.h>
void copy_string(char  from[], char to[]);

int main()
{	
	char a[] = "I am a teacher.";
	char b[] = "You are a student.";
	printf("string_a=%s\n string_b=%s\n", a, b);
	printf("copy string_a to string_b : \n");
		copy_string(a, b);   /* 数组名作参数是地址传递*/
	printf("\nstring_a = %s\nstring_b = %s\n",a,b);
	
	return 0;
}
void copy_string(char  from[], char to[])
{
	int i = 0;
	while (from[i] != '\0')
	{
		to[i] = from[i];  i++;
	}
	to[i] = '\0';
}

结果:
在这里插入图片描述
【字符指针变量作形参】

#include <stdio.h>

void FuncPArs(char *s)
 {
	printf("Result:%s\n", s);
}

int main()
{
	char rsa[] = "Welcome To C/C++.\n";
	FuncPArs(rsa);

	return 0;
}

结果:
在这里插入图片描述

对使用字符指针变量和字符数组的讨论

char *cp; 与 char str[20]; 的区别
str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址
赋值方式:
字符数组只能对元素赋值。 char str[20];
str=“I love China!”; ()
字符指针变量可以用: char *cp;
cp=“I love China!”; ()
赋初值:char *cp=“China!”; 等价 char *cp; cp=“China!”;
char str[14]={“China”};不等价char str[14]; str[ ]=“China” ()

【用下标法引用指针变量所指的字符串中的字符】

#include <stdio.h>

int main()
{
	char *a = "I love China!"; int i;
	printf("The sixth charcter is %c\n", a[5]);
	for (i = 0; a[i] != '\0'; i++)
		printf("%c", a[i]);
	printf("\n");

	return 0;
}

结果如下:
在这里插入图片描述
在这里插入图片描述
用指针变量指向的格式字符串代替printf中的格式字符串(可变格式输出函数)char *format; format="a=%d,b=%f\n"; printf(format,a,b);相对于:` printf("a=%d,b=%f\n"a,b);
可以用字符数组实现:

   char format[ ]="a=%d,b=%f\n";
   printf(format,a,b);

在这里插入图片描述

二、函数指针与指针函数

函数指针的实质(还是指针变量)
函数指针定义格式

类型名 (*函数名)(函数参数列表);
int (*pfun)(int, int);

函数指针的定义_赋值_调用
void FuncTest(void) //定义一个函数,以方便下面定义函数指针
{
printf(“FunPointer DemoTestFunc.\n”);
}

【案例如下】

void (*pFunc)(void);// 函数指针定义
pFunc = FuncTest;   // 函数指针赋值
(*pFunc)();         // 函数指针调用;用函数指针来调用以调用该函数,注意*pFunc要用()括起来
pFunc();            // 调用的第二种写法,效果和上面一样

函数指针作用:函数指针有两个用途:调用函数和做函数的参数。

注意:函数指针声明为指针,它与变量指针不同之处是,它不是指向变量,而是指向函数。

(1)函数指针的实质还是指针,还是指针变量。本身占4字节;

(2)函数指针、数组指针、普通指针之间并没有本质区别,区别在于指针指向的内容是什么;

(3)函数的实质是一段代码,这一段代码在内存中是连续分布的(一个函数的大括号括起来的所有语句将来编译出来生成的可执行程序是连续的),所以对于函数来说很关键的就是函数中的第一句代码的地址,这个地址就是所谓的函数地址,在C语言中用函数名这个符号来表示;

(4)结合函数的实质,函数指针其实就是一个普通变量,这个普通变量的类型是函数指针变量类型,它的值就是某个函数的地址(也就是它的函数名这个符号在编译器中对应的地址值)。

指针函数实质是一个函数
指针函数实质是一个函数。函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。

*指针函数定义格式:类型名 函数名(函数参数列表);
int *pfun(int, int);

指针函数的声明_定义_调用

int * sum(int x);   		//指针函数的声明;返回类型位一个指针变量 可以通过*p来获取值

int * sum(int x) 			//指针函数的定义
{       
	int static sum = 0;   	//static 修身的变量在数据段;不会被函数栈回收
	int *p;
	int i;
	for (i = 1; i <= x; i++)
	{
		sum += i;  // sum=sum+i;
		return p;     	//返回类型是某一类型的指针
	}
}

int *p1;
p1 = fun(a);      			//指针函数的调用

指针函数作用:可以使代码更简洁并在一定程度节约内存;如当你需要返回一个数组中的元素时,你就只需返回首元素的地址给调用函数,调用函数即可操作该数组(让函数返回多个值)。

或者是malloc函数动态分配内存,返回该内存的地址给另外一个函数,另一个函数才好操作该内存。当然还有其他的作用,请读者自行在实践中体会。

注意:指针函数本质是一个函数,使用方法与普通函数没什么两样。既然是函数,就与变量不一样。变量需要定义、赋值、调用(比如函数指针);而函数需要声明、定义、调用。

【工程案例】
输入第几周的第几天获取这天是这个月的几号


#include<stdio.h>
int * GetDate(int wk, int dy);	// 声明指针函数
int main()
{	
        int wk, dy;	
        do 
        {
                 printf("Enter week(1 - 5)day(1 - 7)\n");
	   scanf_s("%d%d", &wk, &dy);
        } while (wk < 1 || wk>5 || dy < 1 || dy>7);
        printf("%d\n", *GetDate(wk, dy));	
	// 调用,GetDate()函数返回的是一个指针(地址)
	// * GetDate()则是取其内容
        return 0;
}
int * GetDate(int wk, int dy)
{
         static int calendar[5][7] = { 
	{ 1, 2, 3, 4, 5, 6, 7 },
	{ 8, 9, 10, 11, 12, 13, 14 },
	{ 15, 16, 17, 18, 19, 20, 21 },
	{ 22, 23, 24, 25, 26, 27, 28 },
	{ 29, 30, 31, -1 } };
        //返回一个地址
        return &calendar[wk - 1][dy - 1]; 
}

结果如下:
在这里插入图片描述

## 三、数组指针与指针数组

【工程案例】

#include <stdio.h>

int main()
{
	int x = 89;
	int y = 92;

	int *p[2];	// 指针数组  元素里面全部都是指针
	printf("x的地址:%p , y的地址:%p\n",&x,&y);

	p[0] = &x;	p[1] = &y;
	printf("p[0]的值:%p , p[1]的值:%p\n", p[0],p[1]);
	printf("\n输出指针数组所指向地址里面的值:\np[0]的值:%d , p[1]的值:%d\n", *p[0], *p[1]);
	return 0;
}

在这里插入图片描述

在这里插入图片描述
【工程案例】

#include <stdio.h>

// 函数申明
void mymemset(void *data, int num, int byteSize);

int main()
{	
	int nums[20];
	mymemset(nums, 0, sizeof(nums));
	int i, len = sizeof(nums) / sizeof(int);
	for (i = 0; i<len; i++) 
	{
		printf("%d ", nums[i]);
	}
	printf("\n");
	return 0;
}
void mymemset(void *data, int num, int byteSize)
{	
// char就是一个字节,而计算机中是以字节为单位存储的
	char *ptr = (char*)data;
	int i;
	for (i = 0; i<byteSize; i++) 
	{
		*ptr = num;
		ptr++;
	}
}

结果如下:
在这里插入图片描述
在这里插入图片描述
一、函数参数传递方式之一(值传递)

#include <stdio.h>
void ExceFun(int x, int y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;
	printf("x=%d, y=%d\n", x, y);
}
int main()
{
	int a = 89, b = 65;
	ExceFun(a, b);
	printf("a=%d, b=%d\n", a, b);
	return 0;
}

二、函数参数传递方式之二(地址传递)

#include <stdio.h> 
void ExceFun(int *px,int *py)
{
	int temp;
	temp=*px;
	*px=*py;
	*py=temp;
	printf("*px=%d, *py=%d\n", *px,*py);
}
int main( )
{
	int a=89, b=65;
	ExceFun(&a,&b);
	printf("a=%d, b=%d\n",a,b);
	return 0;
}
发布了22 篇原创文章 · 获赞 26 · 访问量 512

猜你喜欢

转载自blog.csdn.net/weixin_45525272/article/details/104296525