当前位置: 首页> 房产> 家装 > 梧州市地图疫情最新消息_青海网站建设策划_网站seo优化_嘉兴seo外包

梧州市地图疫情最新消息_青海网站建设策划_网站seo优化_嘉兴seo外包

时间:2025/7/14 7:02:22来源:https://blog.csdn.net/jk1206/article/details/128521515 浏览次数:0次
梧州市地图疫情最新消息_青海网站建设策划_网站seo优化_嘉兴seo外包

序言:

前面概要:

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4. 指针的运算

1.字符指针 

一般情况有:

int main()
{char ch = 'a';char *pc = &ch;*pc = 'a';return 0;
}

还有这种:

#include<stdio.h>
int main()
{const char* pc = "abcdef";printf("%c\n", *pc);return 0;
}

 这里并不是把abcdef这个字符串放到字符指针pc里,而是将字符串的首地址放到字符指针pc里

ba256783b30241199ea3391ace5ecf3f.png

#include <stdio.h>
int main()
{const char str1[] = "abcdef";const char str2[] = "abcdef";const char* str3 = "abcdef";const char* str4 = "abcdef";if (str1 == str2)printf("str1 == str2\n");elseprintf("str1 != str2\n");if (str3 == str4)printf("str3 == str4\n");elseprintf("str3 != str4\n");return 0;
}

 str1[]创建了一个数组,存放了 a b c d e f \0

 str2[]创建了一个数组,存放了 a b c d e f \0

创建了2个数组,所以它们的首地址的地址是不一样的。

这里str1和str2指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当 几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。

const char* str3 = "abcdef";

是一个常量字符串,是无法改变的,这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。所以结果应该是:

8a956b582f0f419a971cc8398404848f.png

所以str1和str2不同,str3和str4不同。

 2.指针数组

指针数组是一个存放指针的数组。
int* arr1[10]; //存放整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
#include<stdio.h>
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 3,4,5,6,7 };int arr3[5] = { 5,6,7,8,9 };int* pc[3] = { arr1,arr2,arr3 };  //将arr1,arr2,arr3的首地址存放在指针数组里int i = 0;for (i = 0; i < 3; i++)	{int j = 0;for (j = 0; j < 5; j++){printf("%d", *(pc[i] + j));//通过pc[i] + j 可以访问到某个数组里的某个数据,这就成了二维数组//printf("%d", pc[i][j]);这两种打印结果是等价的}printf("\n");}return 0;
}

3.数组指针 

1.定义

数组指针是指针?还是数组?
答案是:指针。
那数组指针应该是:能够指向数组的指针。
例如:下面p1 和p2哪个是数组指针,哪个是指针数组?
int *p1[10];
int (*p2)[10];
注:
int (*p1)[10];
解释:p1先和*结合,说明p1是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p1是一个 指针,指向一个数组,叫指针数组。
这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p2先和*结合。p2是指针,指向数组,所以int(*p2)[10]是数组指针 。
#include<stdio.h>
int main()
{int a = 10;int* p = &a;int arr[10] = { 0 };printf("%p\n", arr);         //类型:int*printf("%p\n", arr+1);printf("%p\n", &arr[0]);     //类型:int*printf("%p\n", &arr[0]+1);printf("%p\n", &arr);        //类型:int(*)[10]printf("%p\n", &arr+1);return 0;
}

3fed27091fc5413a904256df27367eb8.png

 可以看出arr和&arr[0]的打印结果一样的,也说明了数组名是首元素的地址。

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是 数组的地址,而不是数组首元素的地址。
本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.

2.&数组名   和   数组名    的区别 

数组名该怎么样理解?

通常情况下我们说的数组名都是数组首元素的地址。

但是有两个例外:

1.sizeod(数组名),这里的数组名表示整个数组,sizeof(数组名)是计算的整个数组的大小。

2.&数组名,这里的数组名是表示整个数组,&数组名,取出的是整个数组的地址。

3.数组指针的使用

数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,0};int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量preturn 0;
}
int arr [ 5 ];                 //整型数组    数组5个元素
int * parr1 [ 10 ];         //指针数组,数组10个元素,每个元素是int*类型
int ( * parr2 )[ 10 ];       //parr2是数组指针,该指针指向一个数组,数组是10个元素,每个元素是int类型的
int ( * parr3 [ 10 ])[ 5 ];   //parr3是指针数组,数组10个元素,数组的每个元素类型是int(*)[5]
(判断该类型就把该名称去掉)

4.数组传参,指针传参

一维数组传参 :

#include <stdio.h>
void test(int arr[])          //ok?  可以   传的数组参数,数组接收
{}
void test(int arr[10])        //ok?  可以    数组只是指定了10个元素
{}
void test(int *arr)           //ok?  可以   数组传参可以用数组首元素地址
{}
void test2(int *arr[20])      //ok?  可以    形参写成数组也可以
{}
void test2(int **arr)         //ok?  可以     arr2是int*类型,传int **arr也可以
{}
int main()
{int arr[10] = {0};
int *arr2[20] = {0};test(arr);test2(arr2);
}

二维数组传参:

void test(int arr[3][5])//ok?      可以
{}
void test(int arr[][])//ok?         不可以
{}
void test(int arr[][5])//ok?      可以
{}
//二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
void test(int *arr)//ok?       不可以,数组3行5列,数组名是首元素的地址
{}
void test(int* arr[5])//ok?不可以,传参要么是数组要么是指针,这还是一维数组
{}
void test(int (*arr)[5])//ok?   可以
{}
void test(int **arr)//ok?   不可以,这是个二级指针
{}
int main()
{int arr[3][5] = {0};test(arr);
}
//传参得保证和要传的类型一样

指针传参

#include <stdio.h>
void print(int *p, int sz)
{int i = 0;for(i=0; i<sz; i++){printf("%d\n", *(p+i));}
}
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9};int *p = arr;int sz = sizeof(arr)/sizeof(arr[0]);//一级指针p,传给函数print(p, sz);return 0;
}
//二级指针
#include <stdio.h>
void test(int** ptr)
{printf("num = %d\n", **ptr); 
}
int main()
{int n = 10;int*p = &n;int **pp = &p;test(pp);test(&p);return 0;
}

 5.函数指针

int  Add(int a,int b)
{return a+b;
}
int main()
{int (*pf)(int ,int)=&Add;int (*pf)(int ,int)=Add;return 0;
}
//&函数名和函数名都是函数的地址
//pf是一个存放函数的指针变量——函数指针

 #指针数组,数组指针,函数指针的区分

int main()
{
//指针数组    本质上是数组,里面存放的是指针char* ch[5]
int arr[10]={0};
//数组指针   本质上是指针,存的是地址
int (*pa)[5]=&arr;
//pf是函数指针
int my_strlen(const  char *str)
{
return 0;
}
int (*pf)(const char*)=&my_strlen;
}

 6函数指针数组

是用来存放  函数指针  的数组

int main()
{//pf是函数指针
int my_strlen(const  char *str)
{
return 0;
}
int (*pf)(const char*)=&my_strlen;
//函数指针数组,那么在函数指针上加个数组呗!
int (*pfA[5])(const char*)={&my_strlen};
}

那么能干什么???

下面是一个简易的计算机小代码:

#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a*b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf( "*************************\n" );printf( " 1:add           2:sub \n" );printf( " 3:mul           4:div \n" );printf( "*************************\n" );printf( "请选择:" );scanf( "%d", &input);switch (input){case 1:printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = add(x, y);printf( "ret = %d\n", ret);break;case 2:printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = sub(x, y);printf( "ret = %d\n", ret);break;case 3:printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = mul(x, y);printf( "ret = %d\n", ret);break;case 4:printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = div(x, y);printf( "ret = %d\n", ret);break;case 0:printf("退出程序\n");breark;default:printf( "选择错误\n" );break;}} while (input);return 0;
}

用函数指针数组改一下

#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a*b;
}
int div(int a, int b)
{return a / b;
}
int main()
{
int x, y;int input = 1;int ret = 0;
//从这开始变化int(*p[5])(int x, int y) = { 0, add, sub, mul, div };//这个函数指针数组就像跳转一样就被称为  转移表。while (input){printf( "*************************\n" );printf( " 1:add           2:sub \n" );printf( " 3:mul           4:div \n" );printf( "*************************\n" );printf( "请选择:" );scanf( "%d", &input);if ((input <= 4 && input >= 1)){printf( "输入操作数:" );scanf( "%d %d", &x, &y);ret = (*p[input])(x, y);}elseprintf( "输入有误\n" );printf( "ret = %d\n", ret);}return 0;
}

这样就不需要do while循环中的一直case!

7指向函数指针数组的指针

int main()
{int arr[10];  //整型数组int  (*pa)[10]=&arr;  int (*pf[5])(int ,int);int(*(*ppf)[5](int ,int)=&pf;
//pf是函数指针数组,&pf后,ppf再指向它,那ppf就是指向函数指针数组的指针
}

8回调函数

回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

 

void calc(int (*pf)(int ,int)){int x = 0;int y = 0;int ret = 0;printf("请输入两个操作数:");scanf( "%d %d", &x, &y);ret = pf(x, y);printf( "%d\n", ret);
}int main(){int x, y;int input = 1;int ret = 0;do{printf( "*************************\n" );printf( " 1:add           2:sub \n" );printf( " 3:mul           4:div \n" );printf( "*************************\n" );printf( "请选择:" );scanf( "%d", &input);switch (input){case 1:calc(Add);case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出程序\n");breark;default:printf( "选择错误\n" );break;}} while (input);return 0;
}

 通过定义一个calc函数,把AddSubMulDiv的函数的地址作为参数传给calc函数,去调用这些函数就是回调函数!

关键字:梧州市地图疫情最新消息_青海网站建设策划_网站seo优化_嘉兴seo外包

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: