当前位置:网站首页>过关斩将,擒“指针”(下)
过关斩将,擒“指针”(下)
2022-06-27 17:00:00 【拼命阿紫】
美丽的外貌千篇一律,有趣的灵魂万里挑一
指针是C语言的灵魂
应该有不少小伙伴对指针还是比较迷迷糊糊的吧
本期 阿紫 接着带大家一起过关斩将,擒 “ 指针 ”

目录
1.字符指针
字符指针:指向字符的指针,指针类型为 char*
char ch = 'a';
char* pc = &ch;一般使用方法:
#include<stdio.h>
int main()
{
char ch = 'a';
char* pc = &ch;
*pc = 'b';
printf("%c\n", ch);
return 0;
}还有一种使用方法:
#include<stdio.h>
int main()
{
const char* pc = "abcdef";
printf("%s\n", pc);
return 0;
}思考1:为什么 const char* pc = "abcdef" 前面要加 const?
答:因为字符指针 pc 指向的是常量字符串,常量是不能发生改变的,所以加 const 避免修改常量字符串。
思考2:const char* pc = "abcdef",是把 abcdef 字符串放入字符指针变量 pc 中吗?
答:不是,是把字符串中首字符的地址放入了 pc 中,也就是把 a 的地址放在 pc 中 。

面试题:
#include<stdio.h>
int main()
{
char arr[] = { "abcdef" };
char brr[] = { "abcdef" };
const char* crr = "abcdef";
const char* drr = "abcdef";
if (arr == brr)
{
printf("arr and brr are same\n");
}
else
{
printf("arr and brr not are same\n");
}
if (crr == drr)
{
printf("crr and drr are same\n");
}
else
{
printf("crr and drr not are same\n");
}
return 0;
}运行结果:

arr 和 brr 是字符数组,是把 abcdef 存储在字符数组中,它们的内存不是同一块,所以它们的地址也就不相同。而 crr 和 drr 是字符指针,是把 abcdef 常量字符串的首元素地址存储字符指针中,所以它们指向的是同一块内存空间。 
2.指针数组
指针数组:它是一个数组,数组中的每个元素都是类型指针
int* arr[10]; //整形指针的数组首先 arr 先跟 [10] 结合说明它是一个有十个元素数组,每个元素都是 int* 类型的指针。
3.数组指针
3.1数组指针的定义
数组指针:是一个指针,指向的是一个数组
int arr[6] = { 1, 2, 3, 4, 5, 6 };
int(*pi)[6] = &arr;pi 先和 * 结合说明它是一个指针变量,[6] 说明它指向了一个数组,数组中有 6 个元素,int 说明每个元素都是 int 类型。
- 注:[] 的优先级要高于 * 号的,所以必须加上()来保证 p 先和 * 结合。
3.2 &数组名 vs 数组名
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };- 数组名 arr :表示首元素的地址
- &数组名:表示整个数组的地址

arr 和 &arr 它们打印出来的地址虽然一样 ,但它们代表的含义不一样。arr 表示数组首元素的地址,而 &arr 表示整个数组的地址,arr + 1跳过了一个元素,而&arr + 1跳过了整个数组。

sizeof(arr[0])是计算 arr[0] 所占空间大小,而 sizeof(arr)是计算整个数组所占空间大小 。
结论:&数组名 和 sizeof(数组名) 表示整个数组,其余的数组名都表示数组首元素的地址。
3.3数组指针的使用
既然数组指针指向的是数组,那数组指针中存放的也就是数组的地址。
#include<stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int(*pi)[10] = &arr;
return 0;
}把数组 arr 的地址赋值给数组指针变量 p ,但我们一般很少这样写代码 ,因为这样写代码没有任何的意义。
一般我们将数组指针用于二维数组
#include<stdio.h>
void print_arr(int(*arr)[3], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
print_arr(arr, 3, 3);
return 0;
}数组名arr,表示首元素的地址 。但是二维数组的首元素是二维数组的第一行 ,所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址。
学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:
int arr[5];//整型数组
int *parr1[10];//数组指针
int (*parr2)[10];//指针数组
int (*parr3[10])[5];//???int (*parr3[10])[5]:首先 parr3 跟 [10] 结合说明它是一个数组,每个元素都是指针数组类型。
4.函数指针
函数指针:首先是它是一个指针,它指向的是一个函数

函数名和&函数名:都表示函数的地址
要是想保存函数的地址,就得用到函数指针

p 先跟 * 结合 说明它是指针,后面的一个 () 表示它指向了一个无参的函数,前面的 void 表示返回值 void。
《 C陷阱和缺陷 》 这本书中有这样两个代码:
//代码1
(*(void (*)())0)();将 0 强制类型转换为 void(*)() 函数指针类型,那么 0 就被当成了一个函数的地址,然后解引用调用,实际上这就是一次函数调用,调用的是 0 作为地址处的函数。
//代码2
void (*signal(int , void(*)(int)))(int);signal 先跟后面的括号结合,说明 signal 是函数名,函数参数第一个参数是 int,第二个参数是函数指针(该函数指针指向的函数参数是int,返回类型是void),返回值也是一个函数指针,该函数指针指向的函数参数是int,返回类型是void,所以这是一次函数声明。
5.函数指针数组
函数指针数组:首先它是一个数组,数组的每一个元素都是指针指向的是函数。
int(*arr[10])();首先 arr 先跟 [10] 结合说明它是一个数组,数组中的每一个元素都是 int(*)()类型的函数指针。
函数指针数组的用途:转移表
#include<stdio.h>
void menu()
{
printf("*********************\n");
printf("*** 1.add 2.sub ***\n");
printf("*** 3.mul 4.div ***\n");
printf("****** 0.exit *******\n");
printf("*********************\n");
}
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 a, b;
int input = 1;
int ret = 0;
int(*p[5])(int a, int b) = { 0, add, sub, mul, div }; //转移表
while (input)
{
menu();
printf("请选择:");
scanf("%d", &input);
if ((input <= 4 && input >= 1))
{
printf("输入操作数:");
scanf("%d %d", &a, &b);
ret = (*p[input])(a, b);
}
else
printf("输入有误\n");
printf("ret = %d\n", ret);
}
return 0;
}6. 指向函数指针数组的指针
指向函数指针数组的指针 :首先它是一个指针,它指向了一个数组,数组中每个元素都是函数指针。
void(*p)();//函数指针
void(*p1[1])();//函数指针数组
void(*(*p2)[2])();//指向函数指针数组指针7.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。
qosrt 函数使用:
#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
int i = 0;
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);//把一个函数地址传给另一个函数
for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
{
printf( "%d ", arr[i]);
}
printf("\n");
return 0;
}
边栏推荐
- MySQL数据库登录和退出的两种方式
- SQL update batch update
- ABAP随笔-EXCEL-3-批量导入(突破标准函数的9999行)
- The data synchronization tool dataX has officially supported reading and writing tdengine
- Alibaba's mission, vision and core values
- Market status and development prospect forecast of global 4-methyl-2-pentanone industry in 2022
- VSCode 建议你启用 gopls,它到底是个什么东东?
- laravel框架中 定时任务的实现
- Core dynamic Lianke rushes to the scientific innovation board: with an annual revenue of 170million yuan, Beifang Electronics Institute and Zhongcheng venture capital are shareholders
- 你知道 log4j2 各项配置的全部含义吗?带你了解 log4j2 的全部组件
猜你喜欢

SQL update批量更新
![[notice of the Association] notice on holding summer special teacher training in the field of artificial intelligence and Internet of things](/img/ef/5b86170e60a7e03c4db512445540b9.jpg)
[notice of the Association] notice on holding summer special teacher training in the field of artificial intelligence and Internet of things

International School of Digital Economics, South China Institute of technology 𞓜 unified Bert for few shot natural language understanding

新中大冲刺科创板:年营收2.84亿 拟募资5.57亿

Good news - British software 2022 has obtained 10 invention patents!

SQL update batch update

Row to column and column to row in MySQL

Summary of domestic database certification test guide (updated on June 16, 2022)

云原生数据库:数据库的风口,你也可以起飞

SQL update批量更新
随机推荐
Recommend several open source IOT platforms
MFS分布式文件系统
Current market situation and development prospect forecast of global 3,3 ', 4,4' - biphenyltetracarboxylic dianhydride industry in 2022
通过 G1 GC Log 重新认识 G1 垃圾回收器
Win10 LTSC 2021 wsappx CPU usage high
Two methods of MySQL database login and logout
Comment encapsuler un appel à une bibliothèque
Galaxy Kirin V10 system activation
开源之夏 2022 | openGauss 项目中选公布
[elt.zip] openharmony paper Club - witness file compression system erofs
SQL update批量更新
Characteristics of time series data
[cloud based co creation] the "solution" of Digital Travel construction in Colleges and Universities
校园书籍资源共享平台
How to view the index information of MySQL tables?
信息学奥赛一本通 1335:【例2-4】连通块
新中大冲刺科创板:年营收2.84亿 拟募资5.57亿
脉脉热帖:为啥大厂都热衷于造轮子?
The incluxdb cluster function is no longer open source, and the tdengine cluster function is even better
金源高端IPO被终止:曾拟募资7.5亿 儒杉资产与溧阳产投是股东