当前位置: 首页 > news >正文

C语言——指针

地址是由物理的电线上产生的,能够标识唯一一个内存单元。在C语言中,地址也叫做指针。

在32位机器中,有32根地址线。地址是由32个0/1组成的二进制序列,也就是用4个字节来存储地址。

在64位机器中,有64根地址线。地址是由64个0/1组成的二进制序列,也就是用8个字节来存储地址。

指针类型

1. 指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)

type* p;
//说明p是指针变量
//type:说明p指向的对象的类型
//说明p解引用的时候访问的对象的大小是sizeof(type)

2. 指针类型还可以决定指针+1时的步长

  • 整型指针+1,跳过4个字节
  • 字符型指针+1,跳过1个字节
  • type* p  + n,跳过n*sizeof(type)个字节

野指针

野指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

野指针的形成原因:

  1. 指针未初始化
  2. 指针越界访问
  3. 指针指向的空间释放

如何规避野指针:

  1. 指针初始化:明确知道指针类型时,应直接初始化;不知道指针初始化为什么值时,暂时初始化为NULL
  2. 小心指针越界
  3. 指针指向空间释放,及时置NULL
  4. 避免返回局部变量的地址
  5. 指针使用前检查有效性

指针运算

1. 指针 +- 整数

#define N_VALUES 5;
float values[N_VALUES];
float *vp;
for(vp=&values[0];vp<&values[N_VALUES]; )
{*vp++;
}

2. 指针 - 指针

指针 - 指针得到的数值的绝对值时指针和指针之间的元素个数

指针- 指针运算的前提是:两个指针指向同一块空间

int main()
{int arr[10] = { 0 };printf("%d\n", &arr[9] - &arr[0]);  //9return 0;
}

3. 指针的关系运算

地址是有大小的,指针的关系运算就是在比较指针的大小

#define N_VALUES 5;
float values[N_VALUES];
float *vp;for(vp = &values[N_VALUES]; vp > &values[0]; )
{*--vp = 0;
}//简化后
for(vp = &values[N_VALUES - 1];vp >= &values[0]; vp-- )
{*vp = 0;
}
//应避免写成简化后的代码。因为C语言规定:
//允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较
//但是不允许与指向第一个元素之前的那个内存位置的指针进行比较

指针与数组

指针:指针变量的大小是4/8个字节,是专门用来存放地址的

数组:是一块连续的空间,可以存放一个或多个类型相同的数据

二者的联系

数组中,数组名就是数组首元素的地址,数组名==地址==指针

当我们知道数组首元素的地址时,因为数组又是连续存放的,所以可以通过指针来遍历访问数组

二级指针

二级指针是用来存放一级指针变量的地址的

int main()
{int a = 10;int* p = &a;//p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的,是变量就有地址int** pp = &p;//pp是二级指针变量,二级指针变量用来存放一级指针变量的地址 //int* 是在说明pp指向的是int*类型的变量//* 说明pp是指针变量*(*(pp)) = 100; //将100赋给了aprintf("%d\n", a);  //100return 0;
}

指针数组

指针数组是存放指针的数组,数组的每个元素都是指针类型

int arr1[10]; //整型数组——存放整型的数组
char arr2[10];//字符数组——存放字符的数组
int* arr3[10];//指针数组——存放指针的数组
int main()
{int* arr1[10];//存放整型指针的数组char* arr2[10];//存放一级字符指针的数组char** arr3[10];//存放二级字符指针的数组return 0;
}

例:利用指针数组模拟二维数组

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int* parr[] = { arr1,arr2,arr3 };int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 5; j++){printf("%d ", parr[i][j]);  //模拟了一个二维数组,但实际上是三个分开的数组}printf("\n");}return 0;
}

数组指针

数组指针,是指向数组的指针,存放的是数组地址的指针变量

int (*p1)[10];  //数组指针
//*p1是指针,指向的是数组,所以*p1是数组指针变量int* p2[10];  //指针数组

数组指针:是指针,是指向数组的指针

指针数组:是数组,是存放指针的数组

 类比一下整型指针和字符指针

  • 整型指针:指向整型变量的指针,存放整型变量地址的指针变量
  • 字符指针:指向字符变量的指针,存放字符变量地址的指针变量
  • 数组指针:指向数组的指针,存放数组地址的指针变量
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int(*p)[10] = &arr;  //数组的地址,存储到数组指针变量return 0;
}

函数指针

函数指针:就是指向函数的指针

int Add(int x, int y)
{return x + y;
}
int main()
{//类比数组指针/*int arr[10] = { 0 };int(*pa)[10] = &arr;*/printf("%p\n", &Add);printf("%p\n", Add);  //两种写法//函数名是函数的地址//&函数名也是函数的地址int (*pf)(int,int) = &Add;  //pf是函数指针变量//int (*)(int,int)是函数指针类型return 0;
}

函数名表示的是函数的地址。与数组不同的是,&函数名表示的也是函数的地址

数组名表示的是数组首元素的地址

有两个例外

  1. sizeof(数组名),这里的数组名表示的是整个数组
  2. &数组名,这里的数组名表示的也是整个数组

 函数指针数组

函数指针数组是数组,数组的每个元素都是函数指针变量

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;
}
int main()
{int (*pf1)(int, int) = Add;int (*pf2)(int, int) = Sub;int (*pf3)(int, int) = Mul;int (*pf4)(int, int) = Div;//函数指针数组int (*pfArr[4])(int, int) = { Add,Sub,Mul,Div };return 0;
}

指向函数指针数组的指针

int (*(*p)[4](int,int) = &pfArr;  //函数指针数组的地址
//p就是指向函数指针数组的指针

区分函数指针、函数指针数组以及指向函数指针数组的指针

void test(const char* str)
{printf("%s\n", str);
}
int main()
{void (*pf)(const char*) = test;//pf是函数指针变量  pf是变量名void (*pfArr[10])(const char*);//pfArr是存放函数指针的数组   pfArr是数组名void (*(*p)[10])(const char*) = &pfArr;//P是指向函数指针数组的指针  p是变量名return 0;
}

回调函数

 回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应

举个例子:标准库中有一个函数qsort,用来排序,需要包含头文件#include<stdlib.h>

qsort函数的特点:

  1. 使用快速排序的方式
  2. 适用于任意类型的数据
/*void qsort(void* base,  //指向了需要排序的数组的第一个元素size_t num,  //排序元素的个数size_t size,  //一个元素的大小,单位是字节int (*cmp)(const void*,const void*))  //函数指针类型—这个函数指针指向的函数,能够比较base指向数组中的两个元素*//*void* 的指针—无具体类型的指针void* 类型的指针可以接收任意类型的地址
这种类型的指针是不能直接解引用操作的
也不能直接进行指针运算*/#include<stdlib.h>
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;  //控制升序或降序,当前为升序//return *(int*)p2 - *(int*)p1;   //当前为降序
}
void print(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}
}
void test1()  //测试qsort排序整型数据
{int arr[10] = { 9,8,5,4,3,7,6,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);//qsort 默认是升序排序qsort(arr, sz, sizeof(int), cmp_int);print(arr, sz);
}
//测试qsort排序结构体数据
struct Stu
{char name[20];int age;
};
//按照年龄排序
int cmp_stu_by_age(const void* p1, const void* p2)  
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
void test2()   
{struct Stu arr[] = { {"zhangsan",20},{"lisi",16},{"wangwu",19}};int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);}//按照姓名排序
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
void test3()
{struct Stu arr[] = { {"zhangsan",20},{"lisi",16},{"wangwu",19} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);}
int main()
{//test1();//test2();test3();return 0;
}

相关文章:

C语言——指针

地址是由物理的电线上产生的&#xff0c;能够标识唯一一个内存单元。在C语言中&#xff0c;地址也叫做指针。 在32位机器中&#xff0c;有32根地址线。地址是由32个0/1组成的二进制序列&#xff0c;也就是用4个字节来存储地址。 在64位机器中&#xff0c;有64根地址线。地址是…...

手搓二分查找

第一种&#xff1a; 该种方法是若a[mid]目标数&#xff0c;则让r一直等于mid&#xff0c;让l往右移动&#xff0c;一直移动到rl&#xff0c;这时候跳出循环&#xff0c;在循环外判断 但是不能写成让lmid&#xff0c;让r往左移动&#xff0c;比如a[2]key&#xff0c;这时&#x…...

pycharm调试(步过(Step Over)、单步执行(Step Into)、步入(Step Into)、步出(Step Out))

pycharm调试 pycharm调试 pycharm调试为什么要学会调试&#xff1f;1. 步过 (Step Over)2. 单步执行 (Step Into)3. 步入&#xff08;Step Into&#xff09;4. 步出&#xff08;Step Out&#xff09; 为什么要学会调试&#xff1f; 调试可以帮助初学者更深入地理解编程基础&am…...

Linux是什么,该如何学习

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Linux的起源与发展 2、Linux在现代计算机领域…...

C++ | Leetcode C++题解之第7题整数反转

题目&#xff1a; 题解&#xff1a; class Solution { public:int reverse(int x) {int rev 0;while (x ! 0) {if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {return 0;}int digit x % 10;x / 10;rev rev * 10 digit;}return rev;} };...

Linux------一篇博客了解Linux最常用的指令

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;Linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…...

vscode安装通义灵码

作为vscode的插件&#xff0c;直接使用 通义灵码-灵动指间&#xff0c;快码加编&#xff0c;你的智能编码助手 通义灵码&#xff0c;是一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研…...

RIP协议(路由信息协议)

一、RIP协议概述 RIP协议&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是一种基于距离矢量的内部网关协议&#xff0c;即根据跳数来度量路由开销&#xff0c;进行路由选择。 相比于其它路由协议&#xff08;如OSPF、ISIS等&#xff09;&#…...

SpringBoot根据配置类动态加载不同环境下的自定义配置

dev环境配置 Profile({"dev","test"}) PropertySource("classpath:dev.properties") public class DevConfigLoader { }Profile("prod") PropertySource("classpath:prod.properties") public class ProdConfigLoader { }P…...

什么?穷哥们没钱RLHF?跟我一起DPO吧,丐版一样用

本次DPO训练采用TRL的方式来进行训练 Huggingface TRL是一个基于peft的库&#xff0c;它可以让RL步骤变得更灵活、简单&#xff0c;你可以使用这个算法finetune一个模型去生成积极的评论、减少毒性等等。 本次进行DPO的模型是一个500M的GPT-2&#xff0c;目的是训练快&#x…...

【Leetcode笔记】102.二叉树的层序遍历

目录 知识点Leetcode代码&#xff1a;ACM模式代码&#xff1a; 知识点 vector、queue容器的操作 对vector<int> vec;做插入元素操作&#xff1a;vec.push_back(x)。对queue<TreeNode*> que;做插入元素操作&#xff1a;que.push(root);。队列有四个常用的操作&…...

进程的状态

目录 1.操作系统的进程状态 2.Linux系统的进程状态 特殊的进程状态 进程的查看 1.操作系统的进程状态 a.新建&#xff1a;就是新建一个进程 b.运行&#xff1a;PCB结构体在运行队列中排队 c.阻塞&#xff1a;PCB结构体在等待队列中&#xff0c;等待非CPU资源就续 d:挂起…...

spring-boot集成websocket

引入Maven依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>跟随spingboot版本</version> </dependency>后端代码 /*** 开启WebSocket支持*…...

【Python】【Flask】提交表单后报500错误

【背景】 日常用户使用的一个Online的基于Flask做的工具,今天忽然报错,看现象是点击表单提交按钮后发生错误。报500内部错误。 【分析】 用print步步为营接近root cause。 报错对应视图函数的展示部分正常执行。提交表单按钮后的内容全部没有正常执行。 提交表单用的方法是…...

Golang vs Java

目录 前言 一、语言背景与特性 二、性能与效率 三、生态系统与库支持 四、开发体验与工具支持 五、微服务架构设计中的对比 六、总结与建议 前言 在当今的软件开发世界中&#xff0c;选择合适的编程语言对于项目的成功至关重要。GoLang&#xff08;也称为Golang&#x…...

HomePlug AV

目录 HomePlug AV的基本概念基本术语网络概念网络实例 HomePlug AV物理层&#xff08;PHY&#xff09;HomePlug AV OFDM收发器架构PHY的调制模式FC调制和ROBO调制物理层的特点OFDM频域/时域转换开窗/槽式OFDM信号和噪声PHY发送控制——信道自适应PHY帧格式&#xff08;Symbol&a…...

【面试八股总结】超文本传输协议HTTP(二)

参考资料 &#xff1a;小林Coding、阿秀、代码随想录 一、HTTP缓存技术 将资源&#xff08;如网页、图像、脚本等&#xff09;的副本存储在客户端或中间代理服务器上&#xff0c;以便将来的请求可以直接从缓存中获取&#xff0c;而不必重新从服务器下载资源。这有助于减少网…...

SQL Server中视图使用子查询的性能影响与优化方案

在SQL Server中&#xff0c;视图&#xff08;View&#xff09;是一种虚拟的表&#xff0c;其内容由查询定义。在视图中&#xff0c;我们可以使用子查询来组合和呈现数据&#xff0c;这为数据呈现提供了灵活性&#xff0c;但同时也可能带来一些性能上的问题。本文将深入分析视图…...

Adaboost集成学习 | Matlab实现基于SVM-Adaboost支持向量机结合Adaboost集成学习时间序列预测(股票价格预测)

目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 Adaboost集成学习 | 基于SVM-Adaboost支持向量机结合Adaboost集成学习时间序列预测(股票价格预测)基于SVM(支持向量机)和AdaBoost集成学习的时间序列预测(如股票价格预测)是一种结合了两种强大机器学习算…...

Apache DolphinScheduler 【安装部署】

前言 今天来学习一下 DolphinScheduler &#xff0c;这是一个任务调度工具&#xff0c;现在用的比较火爆。 1、安装部署 1.0、准备工作 1.0.1、集群规划 dolphinscheduler 比较吃内存&#xff0c;所以尽量给 master 节点多分配一点内存&#xff0c;桌面和虚拟机里能关的应用…...

【随笔】Git -- 高级命令(上篇)(六)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…...

java中Date类,SimpleDateFormat类和Calendar类

Date类 public Date() 创建一个Date对象&#xff0c;代表的是系统当前此刻的日期时间 public Date(long date) Constructs a Date object using the given milliseconds time value. 把时间毫秒值转变成Date日期对象 public void setTime(long date) Sets an existing Date ob…...

施耐德 PLC 控制系统 产品 + 软件总体介绍 2020

参考 2020.7 官方说明视频&#xff1a;https://www.bilibili.com/video/BV1Mi4y1G7Qc/ 总体说明 施耐德作为工业控制界巨头&#xff08;公认的几大巨头&#xff1a;西门子、AB、施耐德&#xff09;&#xff0c;PLC 控制器产品线很庞大&#xff0c;涵盖了高中低的完整产品线&…...

UniApp 应用发布到苹果商店指南

&#x1f680; 想要让你的 UniApp 应用在苹果商店亮相吗&#xff1f;别着急&#xff0c;让我来带你一步步完成这个重要的任务吧&#xff01;在这篇博客中&#xff0c;我将详细介绍如何将 UniApp 应用顺利发布到苹果商店&#xff0c;让你的应用跻身于苹果生态之中。 引言 &…...

KamaCoder 46. 携带研究材料(第六期模拟笔试)

题目描述 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等&#xff0c;它们各自占据不同的空间&#xff0…...

MySQL的基本操作(超详细)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 &#x1f4d4;&#xff08;零基础&#xff09;专栏&#xff1a;MSQL数据库 欢迎&#x1f64f;点赞&…...

自动驾驶之心规划控制笔记

Search-based Path Planning Methods Path Finding Problem 一般来说指标有距离,耗费时间,能量,或者多目标。 左图是拓扑地图,蓝色的点就是顶点,绿色的线是连接关系。最后得到的是一个从哪里走的一个最优,并非精细解。 右图是栅格地图,这个搜索出来的是在相对分辨率比…...

Linux中部署Java jar 包 shell 脚本

Linux中部署Java jar 包 shell 脚本 #!/bin/bash set -e# 基础 # export JAVA_HOME/work/programs/jdk/jdk1.8.0_181 # export PATHPATH$PATH:$JAVA_HOME/bin # export CLASSPATH$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarDATE$(date %Y%m%d%…...

auto.js v1.4.4 实现自动打卡

一、使用场景 所在公司的打卡软件可以单独变成一个可以点击的APP&#xff0c;所以只需要实现以下步骤&#xff1a; 自动解锁屏幕返回主屏幕并打卡锁定屏幕需要的环境&#xff1a; 手机端下载并且安装 auto.js v4.1.1 PC端VS安装对应的插件学习资料 B站学习资料 对应 第三期&am…...

【Linux实验室】NFS、DHCP的搭建

NFS、DHCP的搭建 1、nfs服务搭建及测试什么是NFS&#xff1f;环境准备服务端机器安装nfs-utils和rpcbind包启动NFS服务创建/data/NFSdata目录&#xff0c;配置nfs文件启动服务挂载测试在服务端在共享目录下创建文件测试在客户端在共享目录下创建文件 2、dhcp服务搭建及测试什么…...

wordpress自带高亮/百度自媒体怎么注册

泰波那契序列 Tn 定义如下&#xff1a; T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2 给你整数 n&#xff0c;请返回第 n 个泰波那契数 Tn 的值。 class Solution { public:int tribonacci(int n) {//由于n>3的时候才满足Tn3 Tn Tn1 Tn2&#xff0…...

闵行做网站费用/个人免费网站建设

工具说明 iwconfig类似于ifconfig(8)&#xff0c;但专门用于无线接口。它用于设置特定于无线操作的网络接口的参数(例如:频率)。还可以使用iwconfig来显示这些参数和无线统计信息(从/proc/net/wireless中提取)所有这些参数和统计数据都依赖于设备。每个驱动程序根据硬件支持只…...

静态网站用什么做最快/广州白云区最新信息

有两个插件可以用 actiBPMActiviti BPMN visualizer 两款插件直接在IDEA插件市场搜索就可以搜到&#xff0c;也可以到官方网站的插件仓库也可以找到。 JetBrains插件市场&#xff1a;https://plugins.jetbrains.com/ 我正在使用的IDEA版本是2020.3&#xff0c;而actiBPM不兼容…...

咸阳做网站公司/竞价账户托管哪家好

在调参记录14里&#xff0c;只有2个残差模块&#xff0c;结果遭遇欠拟合了。这次增加一个残差模块&#xff0c;试一试在Cifar10数据集上的效果。自适应参数化ReLU激活函数的基本原理如下&#xff1a;自适应参数化ReLU激活函数Keras程序如下&#xff1a;#!/usr/bin/env python3#…...

学做网站什么语言合适/深圳关键词优化公司哪家好

问题其实不是最终目的&#xff0c;罗列问题主要是为了找到一些研究的具体方向。作为我自己&#xff0c;就是希望能明确一下接下来深入学习的切入点。推荐系统发展到现在已经得到了广泛的应用&#xff0c;但还存在一些问题。 热点核心问题就是数据稀疏性。很容易理解&#xff0c…...

移动版wordpress主题/怎么在百度上发表文章

当手机中的应用越来越多、绑定的服务也越来越多时&#xff0c;谁会想到一条短信引发的连锁反应&#xff0c;能让一个人在一夜间倾家荡产&#xff1f;近日&#xff0c;北京许先生的遭遇《中国移动&#xff0c;请你告诉我&#xff0c;为什么一条短信就能骗走我所有的财产&#xf…...