C语言——指针详解(必收藏)
目录
1.什么是指针?
1.1概念
1.2指针的大小
1.3指针类型的作用
2.野指针
2.1野指针产生的原因
2.2 如何规避野指针
3.指针运算
3.1指针+-整数
3.2指针-指针
3.3 指针的关系运算
4. 二级指针
5. 数组名
*6.指针数组和数组指针
6.1指针数组
*6.2数组指针
6.3举例区别含义
7.数组参数和指针参数
7.1数组参数
7.2指针传参
8.函数指针
9.函数指针数组
9.1指向函数指针数组的指针
*10.回调函数
1.什么是指针?
1.1概念
简单的来说,指针就是地址。我们口头上说的指针其实指的是指针变量。指针变量就是一个存放地址的变量。
1.2指针的大小
指针在32位机器下是4个字节,在64位机器下是8个字节。注:(指针的大小与类型无关)
1.3指针类型的作用
上面涉及到指针的大小与指针类型无关,那么指针类型的作用是什么呢?
指针解引用访问,使用的访问权限是多少 话不多说,上图!
当一个int* 的指针+1,跳过4个字节;当一个char* 的指针+1,跳过1个字节。
同理,对于(指针+-整数)类的题也是如上的原理。
2.野指针
野指针顾名思义,指针指向的位置不可知,就像没有主人的流浪狗。
2.1野指针产生的原因
指针未被初始化
指针越界访问
指针指向的空间释放
对于前两点比较好理解,下面对第三点进行解释:
int* test( )
{int a = 5;return &a;
}
int main()
{int* p = test();*p = 10;return 0;
}
变量a的地址只在test()函数内有效,当把a的地址传给指针p时,因为出了test函数,变量a的空间地址释放,导致p变成了野指针。
2.2 如何规避野指针
- 小心越界
- 及时把指针赋成空指针
- 避免返回局部变量的地址
- 使用指针前检查有效性
3.指针运算
3.1指针+-整数
此部分内容跟指针类型那部分一致
3.2指针-指针
指针-指针的绝对值指的是两个指针之间元素的个数。
前提:两个指针必须指向同一空间
例如:&arr[9]-&arr[0]
下面举个例子实现my_strlen函数
int my_strlen(char str[])
{char* p = str;int count = 0;while (*p != '\0'){p++;count++;}return count;
}int main()
{char arr[] = "abcdef";printf("%d\n",my_strlen(arr));return 0;
}
3.3 指针的关系运算
此部分内容很简单,指针与指针之间比较大小就是指针的关系运算。
例如:定义int* p1,数组int arr[5],p1>&arr[5]。
但是要遵循一个标准:允许指针指向数组元素和指针指向数组最后一个元素后面的位置进行比较,不允许指针指向数组元素与指针指向数组第一个位置的前面进行比较。
4. 二级指针
二级指针就是存放指针地址的指针变量。就像有三个抽屉第一个抽屉的钥匙放在第二个抽屉,第二个抽屉的钥匙放在第三个抽屉。
例如:int a=10;int* p1=&a;int** p2=&p1;
对int* * 做解释:第一个*号代表指针指向的类型是int*的,第二个*代表这个是指针。
5. 数组名
数组名大家都很熟悉,但要区分以下几种情况:
- sizeof(arr):表示的是整个数组的大小。
- &arr: 表示整个数组,取出的是整个数组的大小。
其他情况数组名都表示数组首元素地址。
*6.指针数组和数组指针
6.1指针数组
定义:存放指针的数组(int* arr[])。我们知道有整型类型的数组int arr[],还有字符类型的数组char arr[],指针数组就是指针类型的数组。
以下举个例:
int main()
{int a = 0;int b = 1;int* p1 = &a;int* p2 = &b;int* arr[] = { p1,p2 };//指针数组int* arr[] = { &a,&b };//指针数组return 0;
}
*6.2数组指针
- 定义: 指向数组的指针int (*)[]。
- 应用:遍历整个二维数组
void my_print(int(*p)[5], int x, int y)
{int i = 0;for (i = 0; i < x; i++){int j = 0;for (j = 0; j < y; j++){printf("%d ", *(*(p + i) + j));//printf("%d ", p[i][j]);相似的写法}printf("\n");}
}int main()
{int arr1[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };my_print(arr1, 3, 5);return 0;
}
6.3举例区别含义
- int arr[5] //名为arr的数组,数组里有5个元素,每个元素是int
- int* p1[5] //指针数组,数组里有5个元素,每个元素是int*
- int (*p2)[5] //数组指针,一个指向数组(里面有五个元素,每个元素是int)的指 针
- int (*p3[5])[5] //p3[5]是一个有5个元素的数组,数组里每个元素是int(*)[5]
7.数组参数和指针参数
7.1数组参数
- 一维数组传参: int arr[10](形参部分数组大小可以不写)、int* arr
- 二维数组传参: int arr[3][5]、int arr[][5](行可以省略,列不能)、int (*arr)[5] 不能直接传数组名,二维数组的首地址是第一行元素的首地址
7.2指针传参
- 一级指针传参:int* p
- 二级指针传参:int** p
8.函数指针
- 定义:指向函数的指针int (*pf) (int,int),pf函数返回的类型是int (*)(int,int)
- 对于函数来说如:Add和&Add,意义和值都一样。这一定要区别于数组。
- 特别的,当要调用函数时,定义一个pf的函数指针指向函数。那么int ret=(*pf)(2,3)和int ret=pf (2,3)等价。
**对下面代码的理解:
(*(void(*)())0)() // 将0处强制类型转换为函数指针类型,再对0地址 进行调用
void(*signal(int,void(*)(int)))(int) //这是函数的声明,singal是一个函数,传进去两个 参数的类型是int和void(*)(int),signal函数的返回值 类型是void(*)(int)。
9.函数指针数组
- 定义:存放函数指针类型元素的数组
- 应用:实现计算器
#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 Div(int x, int y)
{return x / y;
}void menu()
{printf("****************\n");printf("* 1.Add 2.Sub *\n");printf("* 3.Mul 4.Div *\n");printf("*** 0.exit ***\n");printf("****************\n");
}int main()
{menu();int input = 0;printf("请选择:");scanf("%d",&input);int ret = 0;//转移表int(*pfarr[])(int, int) = { 0,Add,Sub,Mul,Div };do{if (input == 0){printf("退出\n");break;}else if (input >= 1 && input <= 4){int x = 0;int y = 0;printf("请输入两个操作数:");scanf("%d%d",&x,&y);ret = pfarr[input](x,y);printf("结果是%d\n",ret);break;}else{printf("选择错误!");}} while (input);return 0;
}
9.1指向函数指针数组的指针
1.定义:int (*(*parr)[4])(int int)=&parr
*10.回调函数
- qsort()函数: 是一个库函数,基于快速排序算法实现的一个排序的函数。优点是,任意类型的数据都能排序。
- qsort()函数的形参定义:
void qsort(void* base(起始地址),size_t num(元素个数),size_t width(一个元素的字节长度),int (*cmp)(const void* e1,const void* e2)(自定义比较函数))
- qsort()函数应用:模拟计算器,排序结构体
//模拟计算器,对上面的代码进行优化
#include<stdio.h>void print(int* str, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", str[i]);}printf("\n");
}void swap(char* e1, char* e2, int width)
{int temp = 0;int i = 0;for (i = 0; i < width; i++){temp = *e1;*e1 = *e2;*e2 = temp;e1++;e2++;}
}int cmp(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);//e1>e2-> >0;e1=e2-> 0;e1<e2-> <0
}int bubble_sort(void* base, int num, int width, int(*cmp)(const int* e1, const int* e2))
{int i = 0;int j = 0;for (i = 0; i < num - 1; i++){for (j = 0; j < num - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0){swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{int arr[] = { 9,8,7,3,5,4,2,1,6,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp);print(arr, sz);return 0;
}
//排序结构体
#include<stdio.h>
struct Student
{char name[20];int age;double score;
};int cmp_name(const void* e1, const void* e2)
{return strcmp(((struct Student*)e1)->name, ((struct Student*)e2)->name);
}int main()
{struct Student arr[] = { {"zhang",17,80.6},{"wang",20,85.2},{"li",19,92.0} };int sz = sizeof (arr) / sizeof (arr[0]);qsort(arr,sz,sizeof (arr[0]),cmp_name);return 0;
}
C语言——指针详解(必收藏)相关推荐
- c语言的指针详解ppt,最全的C语言指针详解.ppt
最全的C语言指针详解.ppt 第6章 指针,6.1 指针定义与使用 6.2 指针与函数 6.3 指针与数组 6.4 指针与字符串 6.5 指针数组与多级指针 6.6 指针与动态内存分配 6.7 指针的 ...
- C语言指针详解(全解)—— 前篇
关于指针的基本概念及相关运算写在了上一篇博客 C语言指针详解(初级)_Seinrich的博客-CSDN博客 本篇博客来详细的解说一下指针,深入探讨指针 一.指针与const const修饰的变量为常变 ...
- C语言指针详解——入门C语言指针,初级指针使用。
原文地址:我的个人博客点击查看 C语言教程第二弹--指针详解 所有学过C语言的人都知道,C语言难在它的指针的使用和理解,今天,我带给大家C语言的指针的教程,供大家学习交流,如果有讲的不对的地方,请给作 ...
- c语言 指针函数 详解,[NOTE-C]C语言指针详解(一)
C语言指针让一切想法变成可能,强转和指针可以看做一项呼风唤雨的利器,但是C语言中指针应用又需要格外的小心,其更灵活的利用内存,因为不当的应用可能引起各种异常,这篇文章就是让我们一起来认识C指针,更好的 ...
- c语言 指针_C 语言指针详解
(给CPP开发者加星标,提升C/C++技能) 作者:C语言与CPP编程 / 自成一派123(本文来自作者投稿) 1为什么使用指针 假如我们定义了 char a='A' ,当需要使用 'A' 时,除了直 ...
- c语言高低位拷贝_C语言指针详解
1为什么使用指针 假如我们定义了 char a='A' ,当需要使用 'A' 时,除了直接调用变量 a ,还可以定义 char *p=&a ,调用 a 的地址,即指向 a 的指针 p ,变量 ...
- 导航编程用c语言还是c加加,C语言/C加加大神程序员老司机带你玩转C语言指针详解...
很多初学编程的小伙伴都会选择C语言作为第一门学习的编程语言,因为C语言作为一门底层基础语言相对于其他的高层语言来说更加容易学习.可以来帮助正在学习编程的小伙伴更加快速的了解计算机原理. 但是初学C语言 ...
- C语言指针详解(新手入门推荐)
目录 指针的理解 字符指针:char * 无类型指针void * 指针数组 数组指针 函数指针 回调函数 函数指针数组 练习 指针和数组笔试题解析 指针的理解 关于指针,我先讲一个故事:一个侦探在案发 ...
- C语言指针详解——后篇
目录 一.指针与数组 编辑 二.数组传参 2.1一维数组传参 2.2二维数组传参 三.函数指针及应用 四.函数指针数组 一.指针与数组 先来看以下代码及运行的结果 #include <stdi ...
- C语言指针详解----指针声明定义赋值
C语言的指针是让新手很头疼的事情,但是由于其太过于灵活,以至于可以很好得的解决一些复杂的问题,因此不得不掌握.我最近正在学习指针相关的内容,因此在这里做一个小的总结.本篇是不涉及到函数以及结构体等复杂 ...
最新文章
- 11位科幻作家参与,首次AI人机共创写作实验启动
- 《Objective-c》-(@property和@synsthesize)
- HLG2040二叉树遍历已知前中,求后
- 在Python中的无参装饰器和有参装饰器
- asp.net 设置分页
- 矩阵低秩张量分解_TKDE 2020 | CTRR:组稀疏约束的紧凑张量环回归
- IOS-RunTime(刨根问底)
- python内建函数是什么意思_Python3内建函数简介,Python3内建函数详解
- Linux C++ 实现线程池
- 【017】◀▶ C#学习(九) - ADO.NET
- 详解div+css相对定位和绝对定位用法
- 机器学习实战Ch02: k-近邻算法
- saspython知乎_银行业为什么喜欢用 sas 而不是 python?
- 图片OCR进行在线的文字识别
- 15 个为编程初学者准备的网站
- es对几十亿数据能达到秒级响应吗_万亿数据下的多维实时分析系统,如何做到亚秒级响应...
- DoS/DDoS是什么
- 2021高考青岛一中成绩查询,2021山东青岛中考成绩怎么查?
- ssh如何登录mysql数据库_怎么通过SSH连接Mysql数据库
- 万能Ghost系统封装教程