🌞欢迎来到C语言的世界
🌈博客主页:卿云阁💌欢迎关注🎉点赞👍收藏⭐️留言📝
🌟本文由卿云阁原创!
🌠本阶段属于锻体阶段,希望各位仙友顺利完成突破
📆首发时间:🌹2021年1月17日🌹
✉️希望可以和大家一起完成进阶之路!
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!
目录
0️⃣✨✨✨指针作为函数参数✨✨✨
1.改变数组中元素的值
#include<stdio.h> void print(int *b) { printf("%d\n",*b+1); *b=26; } void main(void) { int a[6]={1,2,3,4,5,6}; print(a); printf("%d ",a[0]); }
2.利用指针交换两个数的值
#include <stdio.h> int main(void) { void swap(int *x,int *y); int a=11,b=22; swap(&a,&b); printf("%d,%d\n",a,b); return 0; } //形参为指针变量,接收两个int型变量的地址。 void swap(int *x,int *y) { *x=*x+*y; *y=*x-*y; *x=*x-*y; }
1️⃣✨✨✨返回指针值的函数✨✨✨
数据类型 *函数名(参数列表){...}
例:int *fun(int x, int y) {...}
引例;
int add(int a,int b) { return a+b; }
此时返回的是基本类型
例.返回数组里最大值的地址
#include<stdio.h> int *print(int *b) { int max=0; for(int i=0;i<6;i++) { if(b[max]<b[i]) max=i; } return b+max; } int main(void) { int a[6]={18,29,13,4,75,36}; int *p; p=print(a); printf("%d\n",*p); }
2️⃣✨✨✨指向函数的指针✨✨✨
函数就是一系列指令的集合,在调用后,这些指令是存放在一个叫做代码区的内存中。函数名的值也不可更改,而且可以作为一个指针,其值为函数指令序列(代码区)的起始地址值,指向的数据类型称为函数类型。(这一点与数组类似)。 函数是数据类型的一种,在C语言中,函数返回类型、形参类型、个数和顺序完全相同的函数才是同一种类型的函数,只要有一个不同,就不是同一种数据类型。
引例1:
int a[5]; int *p; *p=a;
引例1:指向一维数组的指针
char str[3][10]={"123","456","789"}; char(*ch)[10];
指针变量指向一个函数要怎么定义?
一个函数指针变量的声明格式如下。
返回类型 (*变量名) (参数类型列表);
(1) int (*fun1)(double); //形参为一个double型数据,返回一个int型数据
(2) void (*fun2)(char*); //形参为指向char型数据的指针变量,不返回数据。
(3) double* (*fun3)(double *,int); //形参为一个指向double型数据的指针变量和一个int型变量,返回一个指向double数据的指针。
(4) int (*fun4)(); //没有形参,返回一个int型数据。
同一种类型的函数
1,返回类型
2.形参的个数,顺序。
3.每一个形参的类型
#include<stdio.h> int add(int x, int y) { return x + y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div1(int x, int y) { return x / y; } int main() { int (*p)(int,int); p=sub; //h函数名是地址 int b=p(6,8); printf("%d",b); }
函数名的值也不可更改,而且可以作为一个指针,其值为函数指令序列(代码区)的起始地址值,指向的数据类型称为函数类型。
优化
#include<stdio.h> int add(int x, int y) { return x + y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div1(int x, int y) { return x / y; } int cal(int a,int b,int (*p)(int ,int )) { return p(a,b); } int main() { int a=10,b=40; b=cal(a,b,add); printf("%d",b); }
函数名的值也不可更改,而且可以作为一个指针,其值为函数指令序列(代码区)的起始地址值,指向的数据类型称为函数类型。
3️⃣✨✨✨指向指针的指针✨✨✨
数据类型 **变量名;
int **p; 此变量存放一个指针,这个指针指向另一个指针值(数据类型为指向一个int类型的指针)(p占8个字节)p的数据类型为指向一个int类型的指针。
int **p; int *a; int x=10; a=&x; p=&a;
注意:(1)
int a[3][6]; int **p; p=a; return 0;//错误的
p的数据类型为指向一个int类型的指针。a指向一维数组的指针。
(2)
int **p; **p=5: //错误的
p:(装的是一个地址)此时是乱码的,假设为-1
*p:(装的是一个地址)该空间不一定可用int *a; int x; *a=&x; *a=5; //对的
例.1
给定5个字符串,把它们的首地址放在一个指向char型的一维数组中,char* songs[5]={ "I see", "How are you", " see me", "Thanks", "see you later"};写一个函数,把包含"see"的整个字符串改成"saw"输出#include <stdio.h> #include <string.h> //把含"see"的串修改为"saw",其实就是把对应行的地址值改为串"saw" //所在的地址,并不是修改含有"see"的串。 void convertStr(char **buf,int size) //size接收数组songs的元素个数。 { char **tmp = buf; //遍历每一个字符串,如果包含"see",则修改为saw。 while (buf < tmp + size) { if(strstr(*buf,"see") != NULL) //判断是否包含"see"。 { *buf = "saw"; //把"saw"的首地址值赋给*buf。 } buf++; //buf指向指针类型数据,加1指向下一个指针数据。 } } void printString(char **s,int size) //输出字符串。 { char **start = s; for (;s < start + size;s++) printf("%s\n",*s); //输出首地址为s的串。 } int main(void) { char* songs[5]={ "I see","How are you"," you see me", "Thanks","see you \ later"}; //指向char型的指针数组。 char **p = songs; // p是二级指针,与songs都指向指针类型数据,且 //这个指针数据都指向char型数据。可以赋值。 convertStr(p,5); //调用修改串的函数。 printString(p,5); //输出修改后的结果。 return 0; }
4️⃣✨✨✨void*指针✨✨✨
void *指针变量名; 它与任意指针变量之间可以互相赋值
void *p(p可以接受任何类型的指针)
好处:
现实中有些数据类型不知道,可以通过这个方法改。
m n
拷贝内存#include <stdio.h> #include <stdlib.h> #include <string.h> void swap(void* a, void *b, int size) { void *p = malloc(size); memcpy(p, a, size); memcpy(a, b, size); memcpy(b, p, size); free(p); p=NULL; } int main(void) { int m=6,n=12; short x=10,y=20; swap(&m,&n,sizeof(int)); printf("m=%d,n=%d\n",m,n); swap(&x,&y,sizeof(short)); printf("x=%hd,y=%hd\n",x,y); return 0; }