C语言:指针的进阶

news2024/9/9 0:18:50

指针的进阶

  • 一、字符指针
    • (一)字符指针
    • (二)常量字符串和字符数组
  • 二、指针数组和数组指针
    • (一)指针数组 int *p1[10]
    • (二)数组指针 int (*p2)[10]
  • 三、函数指针
    • (一)函数指针
      • 1、概念
      • 2、两段有趣的代码
        • (1)( * ( void(*)()0) )();
        • (2)void (*signal(int, void (*)(int)))(int);
    • (二)函数指针数组
      • 转移表
    • (三)指向函数指针数组的指针
  • 四、回调函数
    • (一)定义
    • (二)qsort函数
    • (三)qsort自定义实现
  • 五、sizeof 和 strlen 的剖析
    • (一)概念
    • (二)sizeof例题
    • (三)strlen例题
  • 六、指针杂论
    • (一)指针大小
    • (二)指针类型的作用
      • 1、指针的加减
      • 2、解引用和访问权限
      • 3、强大的void指针
    • (三)const修饰指针
    • (四)数组名的理解
  • 八、结束语

一、字符指针

(一)字符指针

字符指针指向的是字符串的首元素地址。

(二)常量字符串和字符数组

常量字符串不可以被修改并且在内存中(只读数据区)只会存在一份,而字符数组可以被修改。
在这里插入图片描述

二、指针数组和数组指针

(一)指针数组 int *p1[10]

指针数组是存放指针的数组。
代码中,arr数组就是指针数组。
使用指针数组,传参打印时使用二级指针接收。
在这里插入图片描述

(二)数组指针 int (*p2)[10]

数组指针是存放数组地址的指针 &arr
二位数组的数组名是第一行元素的地址
传参打印时使用数组指针接收。
在这里插入图片描述

三、函数指针

(一)函数指针

1、概念

指向函数的指针,记得要给指针加上()否则指针变量会和后面的函数调用操作符相结合,编译错误。
在这里插入图片描述

2、两段有趣的代码

(1)( * ( void(*)()0) )();

本质上是调用了0地址处的那个函数。
在这里插入图片描述

(2)void (signal(int, void ()(int)))(int);

在这里插入图片描述

(二)函数指针数组

存放函数指针的数组叫函数叫做函数指针数组。

void test(const char* str)
{
 printf("%s\n", str);
}
int main()
{
 //函数指针pfun
 void (*pfun)(const char*) = test;
 //函数指针的数组pfunArr
 void (*pfunArr[5])(const char* str);
 pfunArr[0] = test;
 //指向函数指针数组pfunArr的指针ppfunArr
 void (*(*ppfunArr)[5])(const char*) = &pfunArr;
 return 0;
}

转移表

利用函数指针数组,我们可以将switch语句改成转移表,这样的代码往往是比较简洁的。
在这里插入图片描述

(三)指向函数指针数组的指针

四、回调函数

(一)定义

当把一个函数的地址作为参数传递给另外一个函数,另一个函数用函数指针类型来接收,被调用的函数就是回调函数。
利用回调函数,我们往往可以简化代码,达到泛型编程。
在这里插入图片描述

(二)qsort函数

void qsort (void* base, size_t num, size_t size,
 int (*compar)(const void*,const void*));

这里我们使用了回调函数,只需要按需求写一个比较方式,qsort将会可以给任何类型的数据进行排序。

struct stu
{
	char name[20];
	int age;
};
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct stu*)p1)->name,
	 ((struct stu*)p2)->name);
	 //记得要强制类型转化,指针才会按照字节数进行访问对应地址
}

(三)qsort自定义实现

在这里插入图片描述

五、sizeof 和 strlen 的剖析

(一)概念

sizeof :是操作符,统计的是字节数量,包括字符串末尾的’\0’。
strlen:字符串函数,遇到’\0’结束,统计字符串长度,如果没有’\0’,结果是随机值。
在这里插入图片描述

在这里插入图片描述

(二)sizeof例题

8/4 表示在32位平台是4个字节,64位平台是8个字节。
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%zd\n", sizeof(a));//        16
	printf("%zd\n", sizeof(a + 0));//    8/4
	printf("%zd\n", sizeof(*a));//       4
	printf("%zd\n", sizeof(a + 1));//    8/4
	printf("%zd\n", sizeof(a[1]));//     4
	printf("%zd\n", sizeof(&a));//       8/4
	printf("%zd\n", sizeof(*&a));//      16
	printf("%zd\n", sizeof(&a + 1));//   8/4
	printf("%zd\n", sizeof(&a[0]));//    8/4
	printf("%zd\n", sizeof(&a[0] + 1));//8/4


	char* p = "abcdef";
	printf("%zd\n", sizeof(p));//p是指针变量。计算的是指针变量p的大小,4/8个字节
	printf("%zd\n", sizeof(&p));//&p是指针变量p的地址,4/8个字节	
	//&p -- char** -- 二级指针
	return 0;
}

(三)strlen例题

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", strlen(arr));//随机值
	printf("%zd\n", strlen(arr + 0));//随机值
	//printf("%zd\n", strlen(*arr));//arr是数组名表示首元素的地址
	//*arr 是首元素 -- 'a' - 97 ,传递给strlen后,strlen 会认为97就是地址,然后去访问内存,err
	//printf("%zd\n", strlen(arr[1]));//'b' -98 //err
	printf("%zd\n", strlen((char*) & arr));//随机值
	printf("%zd\n", strlen((char*) & arr + 1));//随机值
	printf("%zd\n", strlen(&arr[0] + 1));//随机值
	return 0;
}

六、指针杂论

(一)指针大小

指针的大小只和环境有关系。在32位平台下是4个字节,64位平台下是8个字节。

(二)指针类型的作用

不同的指针类型在指针的加减,*(解引用),和访问权限上面有差异

1、指针的加减

我们发现指针相加减的规则是
(类型)*p = a;
p + n = p + n * (sizeof(类型))
在这里插入图片描述

在这里插入图片描述

2、解引用和访问权限

这里要将int类型的地址转换成char*操作,需要进行强制类型转换。
在这里插入图片描述

下面这串代码看似正确,实际上,char*指针的访问权限只有一个字节,所以如果数组中值变大,就会发生错误。
在这里插入图片描述

3、强大的void指针

void指针相当于万能指针,可以将任何类型的变量赋值给它,但是之后指针变量不可以再重新赋值或者直接相加减。
在这里插入图片描述

(三)const修饰指针

const放在后面,指针指向区域不能改动,而放在前面,指针的内容不可修改。
在这里插入图片描述

(四)数组名的理解

一维数组:数组名其实是数组的首元素地址。
二维数组:数组名是第一排元素的地址。
但是有两种情况除外。
1、sizeof(数组名) 代表的是整个数组的大小。
2、&(数组名)代表整个数组的地址。
在这里插入图片描述

八、结束语

相信通过这篇文章,能对指针有更深刻的理解,对指针的应用也有提升。这是小编所希望看到的。大家如果也觉得有帮助,那就动动小手支持下吧!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1958348.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Unity编辑器拓展】GraphView自定义可视化节点

1、创建节点区域脚本 其中的new class UxmlFactory,可以让该元素显示在UI Builder中,我们就可以在Library-Project中看到我们新建的这两个UI元素,就可以拖入我们的UI窗口编辑了 public class NodeTreeViewer : GraphView {public new class…

UnityShaderUI编辑器扩展

前言: 当我们在制作通用Shader的时候,避免不了许多参数混杂在一起,尽管在材质面板已经使用过Header标签来区分,但是较长的Shader参数就会导致冗余,功能块不够简约明了,如图: 对于Shader制作者来…

如何在 VPS 上安装和使用 VirtualMin

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 关于 Virtualmin Virtualmin 是 Webmin 的一个模块,允许对(多个)虚拟专用服务器进行广泛的管理。您…

二进制部署k8s集群之master节点和etcd数据库集群(上)

目录 1.操作系统初始化配置 2.升级Linux内核 3.部署docker引擎 4.部署etcd集群 4.1 了解etcdctl工具对etcd做增删改查 4.2 通过etcdctl工具实现数据库的备份和恢复 5.部署Master组件 6.部署 Worker Node 组件 二进制搭建 Kubernetes v1.20 k8s集群master01&#xff1a…

230.信号量

信号量是一种用于多线程同步的机制,可以控制对共享资源的访问。信号量的基本概念是使用计数器来控制多个线程对共享资源的访问。信号量可以分为两类:计数信号量(Counting Semaphore)和二进制信号量(Binary Semaphore&a…

项目风险管理:从理论到实践的探索

项目风险管理:从理论到实践的探索 前言一、项目风险识别二、项目风险应对策略三、综合应对策略结语 前言 在当今快速变化的商业环境中,项目管理已成为组织实现目标的关键工具。然而,项目的成功往往伴随着各种不确定性和潜在风险。有效的风险管…

JCR一区级 | Matlab实现SO-Transformer-LSTM多变量回归预测(蛇群算法优化)

JCR一区级 | Matlab实现SO-Transformer-LSTM多变量回归预测(蛇群算法优化) 目录 JCR一区级 | Matlab实现SO-Transformer-LSTM多变量回归预测(蛇群算法优化)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】M…

Oracle基础-SQL99标准的表连接方法

SELECT * FROM T_NUM CROSS JOIN T_GROUP; --笛卡尔积 ALTER TABLE T_GROUP RENAME COLUMN GID TO ID; --修改字段名 SELECT * FROM T_NUM NATURAL JOIN T_GROUP; --自然连接 会根据两表同名字段或者主外键自动关联 SELECT * FROM T_NUM JOIN T_GROUP USING(ID); --USING连接&…

正余弦算法作者又提出新算法!徒步优化算法(HOA)-2024年一区顶刊新算法-公式原理详解与性能测评 Matlab代码免费获取

声明:文章是从本人公众号中复制而来,因此,想最新最快了解各类智能优化算法及其改进的朋友,可关注我的公众号:强盛机器学习,不定期会有很多免费代码分享~ 目录 原理简介 算法伪代码 性能测评 参考文献 …

oracle语法介绍

Oracle数据库是关系型数据库管理系统之一,其SQL语法遵循标准的SQL规范,但也有一些自己的扩展。以下是一些Oracle SQL语法的基本示例: 1.选择数据: SELECT * FROM my_table; 1.插入数据: INSERT INTO my_table (colum…

Vue 3 中使用 InMap 绘制热力图

本文由ScriptEcho平台提供技术支持 项目地址:传送门 Vue 3 中使用 InMap 绘制热力图 应用场景介绍 InMap 是一款强大的地图组件库,它提供了一系列丰富的可视化功能,包括热力图。热力图可以将数据点在地图上以颜色编码的方式可视化&#x…

NGINX项目实战

一、nginx四层代理 部署支持4层TCP/UDP代理的Nginx服务器 部署nginx服务器 编译安装必须要使用--with-stream参数开启4层代理模块。 [rootproxy ~]# rm -rf /usr/local/nginx/ #清理环境 [rootproxy nginx-1.16.1]# ./configure --with-http_ssl_module --with-stream #开…

医疗器械产品没有互联网连接,就不适用于网络安全要求吗?

医疗器械产品是否不适用于网络安全要求,需要考虑产品是否具有网络连接功能以进行电子数据交换或远程控制,以及是否采用储存媒介进行电子数据交换。详细解析如下: 一、医疗器械的网络安全要求不仅限于互联网连接 数据交换接口:医疗…

这才是 PHP 高性能框架 Workerman 的立命之本

大家好,我是码农先森。 在这个大家都崇尚高性能的时代,程序员的谈笑间句句都离不开高性能,仿佛嘴角边不挂着「高性能」三个字都会显得自己很 Low,其中众所皆知的 Nginx 就是高性能的代表。有些朋友可能连什么是高性能都不一定理解…

【SPIE独立出版:高录用、快检索】第四届通信、网络与物联网国际学术会议 (CNIoT 2024,8月30-9月1)

为了促进通信、计算机和控制等领域专家学者跨界交流与合作,打造最前沿的交流平台,第四届通信、网络与物联网国际学术会议 (CNIoT 2024)将涉及通信、网络、物联网、IT能量感知技术、人工智能应用等领域。 会议将为专注于该研究领域的国内外优秀…

一键切换阿里yum源(包括其他系统repo镜像查找方法)

一键切换阿里yum源 示例命令其他系统repo镜像GitHub文档 示例命令 # 备份旧源 mv CentOS-Base.repo CentOS-Base.repo.bak # 添加新源(阿里镜像源) wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo其他系统repo镜像 这里的示例是用…

RT-DETR:DETRs Beat YOLOs on Real-time Object Detection (CVPR2024)

DETRs Beat YOLOs on Real-time Object Detection 论文链接:http://arxiv.org/abs/2304.08069 代码链接:https://github.com/lyuwenyu/RT-DETR https://github.com/ultralytics/ultralytics/tree/main/ultralytics/models/rtdetr(已集成到Y…

2024.7.29 作业

1> 写一个日志文件&#xff0c;将程序启动后&#xff0c;每一秒的时间写入到文件中 #include <myhead.h> int main(int argc,const char *argv[]) {FILE *fp NULL;if((fpfopen("./log.txt","r"))NULL) {perror("open error1");return…

使用 Python 实现计算交并比(IoU)的代码示例:

两个矩形框的交集/并集 IOU(A)/(ABC) box_areas(box[2]-box[0])*(box[3]-box[1])boxes_areas(box[:,2]-box[:,0])*(box[:,3]-box[:,1])l_xtorch.maximum(box[0],boxes[:,0])l_ytorch.maximum(box[1],boxes[:,1])r_xtorch.minimum(box[2],boxes[:2])r_ytorch.minimum(box[3],box…

SpringCloud+Vue3主子表插入数据(芋道)

目的&#xff1a;多表联查获取到每个班级里面所有的学生上课的信息。点击消课插入到消课主表和消课子表&#xff0c;主表记录班级信息&#xff0c;消课人员信息&#xff0c;上课时间。子表记录上课学员的信息&#xff0c;学员姓名、手机号、班级名称、班级类型、上课时间、老师…