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

C语言 —— 指针

目录

1. 指针是什么?

2. 指针和指针类型的关系

2.1 指针的解引用

2.2 指针+-整数

3. 野指针

3.1 野指针成因

1. 指针未初始化

2. 指针越界访问

3. 指针指向的空间释放

3.2 如何规避野指针

4. 指针运算

4.1 指针+-整数

4.2 指针-指针

指针-指针的使用

4.3 指针的关系运算

5. 指针和数组

6. 二级指针

7. 指针数组


1. 指针是什么?

指针是什么?
指针理解的2个要点:
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址,口语中说的指针通常指的是指针变量。


我们在初识C语言中知道, 内存是一块很大的空间, 这么大的内存空间如何管理呢?

其实我们是把内存切割成一个个的内存单元, 一个内存单元大小是1byte.

对于要点的理解:

  • 第一点

  • 第二点

当写下以下代码时:

int a = 10;//a是整型变量,占用4个字节的内存空间

意味着要在内存中找4个空间存放a.


指针=指针变量, 指针变量中存放地址, 通过这个地址可以找到一个内存单元.

总结:

  • 指针变量是用来存放地址的,地址是唯一标示一块地址空间的。
  • 指针的大小在32位平台是4个字节,在64位平台是8个字节。

注意下面所使用的环境是x86的环境, 也就是32位的环境. (如果改成x64就是64位的环境)

我们来看一下指针的大小.

int main()
{char* pc = NULL;short* ps = NULL;int* pi = NULL;double* pd = NULL;//sizeof 返回的值的类型是无符号整型  unsigned intprintf("%zu\n", sizeof(pc));printf("%zu\n", sizeof(ps));printf("%zu\n", sizeof(pi));printf("%zu\n", sizeof(pd));return 0;
}

执行结果:

可以看到, 不同类型指针的大小都是4个字节.

既然这样, 不管是创建什么类型的指针, 在32位平台是4个字节,在64位平台是8个字节, 那么为什么还要区分不同类型的指针出来? 而不是直接使用一个统一的指针类型?

C语言并没有使用统一的指针类型, 说明每一种类型的指针都是有意义的, 并不多余.

接下来我们来探讨指针类型的意义.

2. 指针和指针类型的关系

2.1 指针的解引用

我们来看这段代码的效果:

int a = 0x11223344;    
int* pa = &a;
*pa = 0;

通过调试可以看到:

如果把代码改为:

int a = 0x11223344;    
char* pc = (char*)&a;//a原本应该是int*, 而非要赋给char*, 此时进行强转
*pc = 0;

pc是否有能力存下a的地址? 有, pc也是指针变量, 在x86环境下的大小也为4个字节.

我们来调试查看:

所以可以看到, a的地址是可以存到pc中.

但是, 使用的时候会有差异, 即*pc.

注: 上图为重新调试的截图, 所以会和前面的图有地址差异.

可以看到, *pc所修改的内容只有一个字节, 因为pc的类型是char*指针, 所以解引用时只访问了一个字节.

而前面使用int*pc是访问了4个字节.


综上, 我们有以下结论.

指针类型决定了指针在被解引用的时候访问几个字节
如果是int*的指针,解引用访问4个字节
如果是char*的指针,解引用访问1个字节
(还可以推广到其他类型)
这便是指针类型的第一个意义.再来看第二个意义.

2.2 指针+-整数

int main()
{int a = 0x11223344;int*  pa = &a;char* pc = (char*)&a;printf("pa = %p\n", pa);printf("pa+1 = %p\n", pa+1);printf("pc = %p\n", pc);printf("pc+1 = %p\n", pc+1);return 0;
}

执行结果:

所以我们得出以下结论:

指针的类型决定了指针+-1操作的时候,跳过几个字节, 它决定了指针的步长.

3. 野指针

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

3.1 野指针成因

1. 指针未初始化

int main()
{int* p;//p没有初始化,就意味着没有明确的指向//一个局部变量不初始化的话,放的是随机值:0xcccccccc*p = 10;//非法访问内存了,这里的p就是野指针return 0;
}

2. 指针越界访问

int main()
{int arr[10] = { 0 };int* p = arr;//&arr[0]int i = 0;for (i = 0; i <= 10; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*p = i;p++;}return 0;
}

3. 指针指向的空间释放

int* test()
{int a = 10;return &a;
}int main()
{int*p = test();printf("haha\n");printf("abcdef\n");if (p != NULL){printf("%d\n", *p);}return 0;
}

3.2 如何规避野指针

1. 明确的给指针初始化

2. 小心指针越界

3. 指针指向空间释放即使置NULL

4. 避免返回局部变量的地址

5. 指针使用之前检查有效性

4. 指针运算

  • 指针+- 整数
  • 指针-指针
  • 指针的关系运算

4.1 指针+-整数

#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{*vp++ = 0;
}

4.2 指针-指针

指针-指针得到的结果的绝对值是指针和指针之间元素的个数.

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

注意: 不是所有的指针都能相减, 指向同一块空间的2个指针才能相减.

下面写法是错误的:

int arr[10] = { 0 };
char ch[5] = {0};
printf("%d\n", &ch[0] - &arr[5]);//err

指针-指针的使用

使用指针-指针的方式求字符串长度.

显然的, 只需要知道第一个字符的地址和\0的地址就可以知道字符串长度, 两个指针相减即可.
#include <stdio.h>
#include <string.h>int my_strlen(char* str)
{char* start = str;while (*str != '\0'){str++;}return (str - start);
}int main()
{int len = my_strlen("abcdef");printf("%d\n", len);return 0;
}

4.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;
}

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

5. 指针和数组

我们知道:

数组:一组相同类型元素的集合
指针变量:是一个变量,存放的是地址
数组名表示的是数组首元素的地址(两种情况除外)
int main()
{int arr[10] = {0};//arr 是首元素的地址//&arr[0]int* p = arr;//我们可以通过指针来访问数组, 这就是两者的联系int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0; i < sz; i++){printf("%d ", *(p + i));}for (i = 0; i < sz; i++){printf("%p ----- %p\n", &arr[i], p + i);}return 0;
}

6. 二级指针

#include <stdio.h>int main()
{int a = 10;int* pa = &a;//pa是一个指针变量,一级指针变量//*pa = 20;printf("%d\n", a);//pa是变量, 它在内存中也会有自己的内存空间, 那么就能&pa.int** ppa = &pa;//ppa是一个二级指针变量**ppa = 20;return 0;
}
一级指针变量就是如果通过pa找a的话, 找一次就可以了.

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

7. 指针数组

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

我们知道, 创建比较多的相同类型的变量可以使用数组, 那么假设对于这些变量都有对应的指针去存放它们的地址, 是否也能用类似的方式, 去创建一个类型都为指针的数组? 显然是可以的, 也就是说C语言是有这种语法存在的.

int a = 10;
int b = 20;
int c = 30;int* pa = &a;
int* pb = &b;
int* pc = &c;
int arr[10];int* parr[10] = {&a, &b, &c};
int i = 0;
for (i = 0; i < 3; i++)//0 1 2
{printf("%d ", *(parr[i]));
}

int arr1[4] = { 1,2,3,4 };
int arr2[4] = { 2,3,4,5 };
int arr3[4] = { 3,4,5,6 };int* parr[3] = {arr1, arr2, arr3};
int i = 0;
for (i = 0; i < 3; i++)
{int j = 0;for (j = 0; j < 4; j++){printf("%d ", parr[i][j]);}printf("\n");
}

相关文章:

C语言 —— 指针

目录 1. 指针是什么&#xff1f; 2. 指针和指针类型的关系 2.1 指针的解引用 2.2 指针-整数 3. 野指针 3.1 野指针成因 1. 指针未初始化 2. 指针越界访问 3. 指针指向的空间释放 3.2 如何规避野指针 4. 指针运算 4.1 指针-整数 4.2 指针-指针 指针-指针的使用 4.3 指针的关系运…...

淘宝店铺所有商品数据接口,淘宝整店所有商品数据接口,淘宝店铺商品接口,淘宝API接口

淘宝店铺所有商品数据接口可以通过淘宝开放平台获取。以下是具体步骤&#xff1a; 在开放平台注册成为开发者并创建一个应用&#xff0c;获取到所需的 App Key 和 App Secret 等信息。使用获取到的 App Key 和 App Secret 进行签名和认证&#xff0c;获取 Access Token。调用开…...

【Redis】Java客户端使用zset命令

zadd/zrange zcard zrem zscore zrank...

记录一个@Transaction注解引发的bug

记录一个Transactional(readOnly true)注解引发的bug 一、问题代码和报错 1-1 问题代码模拟 引发这个问题的三大要素分别是&#xff1a; 事务注解任意数据库操作数据库操作后执行耗时业务&#xff08;耗时超过数据库配置的超时时间&#xff09; //1.这里是问题的核心之一…...

解决docker使用pandarallel报错OSError: [Errno 28] No space left on device

参考&#xff1a;https://github.com/nalepae/pandarallel/issues/127 在使用pandarallel报错OSError: [Errno 28] No space left on device&#xff0c;根据上述issue发现确实默认使用的MEMORY_FS_ROOT为 /dev/shm&#xff0c;而在docker环境下这个目录大小只有64M&#xff0…...

Javascript自定义页面复制事件

Javascript自定义页面复制事件 – WhiteNights Site 2023年10月13日 文章访问量&#xff1a;90 标签&#xff1a;Javascript 监听copy事件以达到自定义页面复制功能的效果。 写者注 需要注意的是&#xff0c;浏览器的部分拓展插件&#xff08;如迅雷&#xff09;会导致本文…...

Nginx:反向代理(示意图+配置)

示意图&#xff1a; 反向代理 反向代理&#xff08;Reverse Proxy&#xff09;是代理服务器的一种&#xff0c;它代表服务器接收客户端的请求&#xff0c;并将这些请求转发到适当的服务器。当请求在后端服务器完成之后&#xff0c;反向代理搜集请求的响应并将其传输给客户端。…...

macbook笔记本电脑内存怎么清理才能干净流畅?

假如你还在为“你的系统内存不足”的提示所困扰&#xff0c;或者你的Mac电脑突然运行缓慢和卡顿&#xff0c;那么你一般需要认真了解一下macbook内存怎么清理了? MacBook是功能强大的电脑&#xff0c;这点毫无疑问&#xff0c;但是它仍旧会随着时间推移变得运行缓慢。值得庆幸…...

spark 与 mapreduce 对比

Spark 为什么比 MapReduce 快总结 首先澄清几个误区&#xff1a; 1&#xff09;两者都是基于内存计算的&#xff0c;任何计算框架都肯定是基于内存的&#xff0c;所以说网上所说的 Spark 是基于内存计算所以快&#xff0c;显然是错误的。 2&#xff09;DAG 计算模型减少的是磁…...

kafka 相关概念

1 kafka 生产者 kafka 用push的方式把消息推送到topic 每个topic下可以有多个分区&#xff0c; 可以用hash 也可以用轮询的方式指定分区 每个分区内部是可以保证顺序的&#xff0c;但是整体无法保证顺序&#xff0c;除非设置成一个topic只有一个分区。 kafka这种多分区的设置 带…...

Ubuntu下vscode配置OpenCV以及Libtorch

opencv安装 sudo apt-get updatesudo apt-get install libopencv-dev 该方式安装的版本可能比较旧。 测试代码 #include <opencv2/opencv.hpp>#include <iostream>int main() {cv::Mat image cv::imread("t.png");cv::imshow("Image", ima…...

关于共识算法Raft的常见误解

关于共识算法Raft的常见误解 Raft 共识算法最终一致性与线性一致性日志的覆盖与删除Remove节点时需要skip 总结参考文档 Raft 共识算法 最近翻了翻Raft相关的资料&#xff0c;同时也总结了日常工作的一些积累&#xff0c;就当做Raft技术笔记吧。 由于工作的关系&#xff0c;Ra…...

Python学习基础笔记七十——模块和库1

模块和库&#xff1a; 一个python代码文件就实现了功能。功能比较单一。 在企业中&#xff0c;项目开发的文件&#xff0c;可能有成百上千个。 不同的代码文件&#xff0c;实现了不同的功能模块&#xff0c;就像一块块积木一样。这些功能文件整合起来&#xff0c;实现一个完…...

SystemVerilog Assertions应用指南 第一章(1.28章节 内建的系统函数)

SVA提供了几个内建的函数来检查一些最常用的设计条件。 $onehot(expression)—检验表达式满足“one-hot”,换句话说,就是在任意给定的时钟沿,表达式只有一位为高。 $onehot0( expression)—检验表达式满足“ zero one-hot”&#xff0c;换句话说,就是在任意给定…...

正则表达式(自用)

正则表达式 符号概述 分类符号用法示例元字符^以 ***开头$以 ***结尾d匹配数字s匹配任意的空白符.匹配除换行符以外的任意字符w匹配字母或数字或下划线或汉字\转义重复限定符*次数&#xff0c;至少一次至少1次?0次 或者 1次{n}{n,}{n,m}重复n次&#xff1b;n活更多次&#x…...

大厂真题:【模拟】OPPO2023秋招提前批-小欧数组求和

题目描述与示例 题目描述 小欧拿到了一个数组&#xff0c;她有q次操作&#xff0c;每次操作修改一个元素。小欧希望每次修改后得到当前数组所有元素之和。你能帮帮她吗&#xff1f; 输入描述 第一行输入两个正整数n和q&#xff0c;代表数组的大小和操作次数。 第二行输入n…...

Python括号匹配问题

给定一个只包含小写字母的字符串&#xff0c;判断该字符串中的括号是否闭合&#xff0c;如果每个左括号都有对应的右括号&#xff0c;并且括号的嵌套顺序正确&#xff0c;那么括号就能正确闭合。 否则&#xff0c;括号不能正确闭合&#xff0c;字符串中括号仅限于 "("…...

微信小程序备案内容常见问题汇总

一、备案时间点 自2023年09月01日起,新的微信小程序,必须备案后才能上架; 在2024年03月31日前,所有小程序都必须完成备案; 于2024年04月01日起,对未备案小程序进行清退处理。 微信小程序备案系统已于9月4日上线。 二、备案流程 [找备案入口]–[填主体信息]–[填小程…...

无人机新手防炸飞行技巧

不要在室内飞行,容易撞墙。起飞前设置好避障和返航模式。使用模拟器熟练掌握操控。选择开阔环境目视起飞。使用低速档平稳飞行。合理使用避障功能,不要盲目依赖。使用九宫格避障法。留意电量,及时返航。极低电量时放弃强行返航。飞行后及时为电池充电保养。...

webrtc opus 音频编码支持SILK和CELT模式

SILK CELT是指将SILK编解码器和CELT编解码器结合在一起的混合音频编码方案。 SILK&#xff08;Super-wideband audio coding&#xff09;是一种低延迟的音频编解码器&#xff0c;用于实时的语音通信。它提供高质量的音频传输&#xff0c;并且适用于各种比特率和带宽条件。SILK…...

掌握Python爬虫实现网站关键词扩展提升曝光率

目录 一、关键词优化的重要性 二、关键词优化的基本方法 1、选择与网站内容相关的关键词 2、控制关键词的密度和分布 3、关键词的层次布局 三、Python爬虫实现网站关键词扩展 1、确定目标网站 2、分析目标网站的HTML结构 3、编写Python爬虫代码 4、分析爬取到的关键词…...

ajax实现原理

网页应用能够快速地将增量更新呈现在用户界面上&#xff0c;而不需要重载&#xff08;刷新&#xff09;整个页面。这使得程序能够更快地回应用户的操作 Ajax的实现原理 创建Ajax对象 传入请求方式和请求地址 发送请求 获取服务器与客户端的响应数据 xhr.responseText // 1…...

图G的拉普拉斯矩阵为什么由L=D-A定义

图G的拉普拉斯矩阵由LD-A定义&#xff0c;其中D是度矩阵&#xff08;Degree Matrix&#xff09;&#xff0c;A是邻接矩阵&#xff08;Adjacency Matrix&#xff09;。这种定义方式有以下原因&#xff1a; 1. 度矩阵D&#xff1a;度矩阵是一个对角矩阵&#xff0c;其对角线上的…...

实习项目遇到的bug

问题1&#xff1a; 大概是因为没设置ts类型&#xff0c;它查不到的问题&#xff0c;不定义的话加上问号&#xff0c;加上可选链就不会报错了 {{bizEquipmentInfo.lastUnlockingVO?.lastUnlockingTime.replace(T, )? bizEquipmentInfo.lastUnlockingVO?.lastUnlockingTime.r…...

python selenium下载一个合适的chromedriver.exe(稳定版本)

可以使用该脚本来进行下载&#xff1a; 下载前需要安装如下的依赖 requests2.27.1 selenium4.14.0 webdriver_manager4.0.1下载脚本代码&#xff1a; import json import subprocess import shutil import os import time import zipfileimport requests from webdriver_mana…...

RabbitMQ从0到1完整学习笔记一:《基础篇》

目录 启篇 一、初识MQ 1.1 同步调用 1.2异步调用 1.3 技术选型 二、RabbitMQ 架构 2.2 收发消息 2.2.1 交换机 2.2.2 队列 2.2.3 绑定关系 2.2.4 发送消息 2.3 数据隔离 2.3.1 用户管理 2.3.2 virtual host 三、SpringAMQP 3.1 案例入门 3.1.1 导入依赖 3.1.2 消息发送 3.1.2 消…...

什么是时间冒泡?

时间冒泡是指当一个元素触发一个事件时&#xff0c;事件会像水泡一样&#xff0c;从触发元素向它的所有父节点传播&#xff0c;一直到根节点都会接收到此事件 1。如果父元素中注册了相应的事件处理函数&#xff0c;那么尽管事件在子节点触发的&#xff0c;在父元素上注册的事件…...

Go语言入门心法(三): 接口

Go语言入门心法(一) Go语言入门心法(二): 结构体 Go语言入门心法(三): 接口 一&#xff1a;go语言接口认知 Go语言中接口认知升维:解决人生问题的自我引导法则: 复盘思维|结构化思维|金字塔思维|体系化思维|系统化思维 面向对象编程(oop)三大特性: 封装,继承,多态 Go语言中,可…...

leetcode:210. 课程表 II

课程表 II 提示 中等 889 相关企业 现在你总共有 numCourses 门课需要选&#xff0c;记为 0 到 numCourses - 1。给你一个数组 prerequisites &#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示在选修课程 ai 前 必须 先选修 bi 。 例如&#xff0c;想要学习课程…...

[MT8766][Android12] 使用谷歌LPA实现ESIM功能的流程

文章目录 开发平台基本信息问题描述实现流程 其他问题 开发平台基本信息 芯片: MT8766 版本: Android 12 kernel: msm-4.19 问题描述 客户需要我们设备支持ESIM功能&#xff0c;5月份的时候在高通6125上面预研过ESIM功能&#xff0c;当时ESIM供应商是Links field&#xff0c…...