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

【C语言】 详谈指针

 

☃️内容专栏:【C语言】初阶部分

☃️本文概括:继初识C语言,对C语言指针初阶部分进行归纳与总结。

☃️本文作者:花香碟自来_ 

☃️发布时间:2023.2.17

目录

一、指针和指针类型

1.1 指针

 1.2 指针类型

其一(指针的解引用):

 其二(指针+-整数):

1.3指针的类型的应用

二、野指针

2.1野指针成因

1. 指针未初始化

 2.指针越界访问

3.指针指向的空间释放

2.2 如何规避野指针

三、指针运算

3.1指针加减整数

3.2指针减去指针

3.3指针的关系运算

四、指针和数组

五、二级指针

六、指针数组


一、指针和指针类型

1.1 指针

在初识C语言中,我们就知道:

  1. 指针是内存中一个最小单元的编号,也就是地址(编号 == 地址 == 指针)
  2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
  3. 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

所以我们有总结:

  1.  指针变量是用来存放地址的,地址是唯一标示一个内存单元的。
  2.  指针的大小在32位平台是4个字节,在64位平台是8个字节 
int main()
{int a = 10;//a是整型 占用四个字节的内存空间,每个字节都有对应的地址编号int* pa = &a;//pa是指针变量//&a得到是a的地址(指针),其实得到的是a所占内存中4个字节的起始地址(第一个字节的地址)return 0;
}

 1.2 指针类型

我们知道变量都有不同的类型,char 、int 、short、float……每个类型对应的大小都不同。而指针变量也有相应的类型。

指针的定义方式是: type + * 。
其实:
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。

我们知道指针变量的大小与数据类型无关,在32位平台上都是4个字节,那么我们只需定义一个指针变量就可以了呀,其实不然,下面就此讨论指针类型的意义。

指针类型的意义:

其一(指针的解引用):

观察以下代码

我们通过调试—>内存—>&a—>将十六进制的数字“0x11223344”存储到了a当中,a的地址为0x00aff998,我们*pa会发生什么呢?
我们继续按F10调试,a的4个字节的大小都变成了0.

如果我们强制把a的地址存放到char*的空间里面去(会报警告,显示从int* 到char* 的类型不兼容,这里不影响调试),观察以下代码

这时,我们发现*pc = 0,调试后,只是将第一个字节的数据改为了0,
总结:指针类型决定了,在解引用指针的时候有多大权限(能访问几个字节)。
比如:
char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

 其二(指针+-整数):

 观察以下代码

 我们分别把a的地址存放到int* 和char* 里面去,分别打印pa 、pa + 1以及pc ,pc + 1的地址,我们不难发现

  • pa与pc的地址是一样的,因为pa与pc存放的都是a的起始地址。
  • pa + 1则在pa指针变量的基础上跳过了4个字节的大小,因为pa指针变量指向的是一个int类型,所以 + 1的操作就是跳过一个整型的大小。
  • pc + 1同理,因为pc指针变量指向的是一个char类型的大小,+ 1就会跳过一个字符类型的大小。

所以,pa+n等于加上了n*sizeof(int),pc+n等于加上了n*sizeof(char)

        总结:指针的类型决定了指针向前或者向后走一步有多大(距离)

1.3指针的类型的应用

#include<stdio.h>
int main()
{int arr[10] = { 0 };int* p = &arr[0];int i = 0;for (i = 0; i < 10; i++){*p = i + 1;p++;}for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

 运行结果:

二、野指针

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

2.1野指针成因

1. 指针未初始化

int main()
{int* p; //未初始化,p指向位置的是未知的(随机的),p就是野指针*p = 10;return 0;
}

 2.指针越界访问

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

3.指针指向的空间释放

int* test()
{int a = 10;return &a;
}
int main()
{int* p = test();*p = 20;return 0;
}

test调用之后返回的是局部变量的地址,但是实际的a变量不存在了,已经出了函数的作用域,已经销毁了,此时的p指针变量就是一个野指针。

2.2 如何规避野指针

  1.   指针初始化
  2.   小心指针越界
  3.   指针指向空间释放,及时置NULL
  4.   避免返回局部变量的地址
  5.   指针使用之前检查有效性
#include <stdio.h>
int main()
{int *p = NULL;int a = 10;p = &a;if(p != NULL){*p = 20;}return 0;
}

三、指针运算

3.1指针加减整数

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

3.2指针减去指针

我们思考以下代码,

#include<stdio.h>
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int n = &arr[9] - &arr[0];//得到的是之间元素的个数printf("%d", n);return 0;
}

我们在前面知道,指针加上一个整数等于一个指针,那么在这里我们其实就不难发现,指针减去指针得到的是两个指针之间的元素个数。

学到这里,我们是不是可以用指针模拟实现一个strlen库函数

代码如下:

#include<stdio.h>
int my_strlen(char* str)
{char* begin = str;while (*str != '\0'){str++;}return str - begin;
}
int main()
{char str[] = "abcdef";printf("%d", my_strlen(str));return 0;
}

3.3指针的关系运算

我们将3.1的代码修改一下,得到以下代码

代码1:

#define N_VALUES 5
int main()
{float values[N_VALUES];float* vp;for(vp = &values[N_VALUES]; vp > &values[0];){*--vp = 0;}return 0;
}

 代码简化,将代码修改一种方式:

代码2:

#define N_VALUES 5
int main()
{float values[N_VALUES];float* vp;for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--){*vp = 0;}return 0;
}

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

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

四、指针和数组

指针就是指针,数组就是数组。但指针和数组是有关联的。

 数组名是数组首元素的地址。(两种情况除外,前面提到过,可以看看数组章节部分的知识)

#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,0};int* p = arr;//p存放的是数组首元素的地址printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}

 利用指针访问数组的元素

将int arr[10] = {0} 的元素通过指针初始化为1 2 3 4 … 10.

#include<stdio.h>
int main()
{int arr[10] = { 0 };int* p = arr;int i = 0;	for (i = 0; i <  10; i++){*p = i + 1;//存放数据p++;}//打印p = arr;for (i = 0; i < 10; i++){printf("%d ",*(p + i));}return 0;
}

五、二级指针

我们知道,指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里呢?

这里,我们就要讲到二级指针的概念。

#include<stdio.h>
int main()
{int a = 10; //a在内存中申请了4个字节的空间//一级指针int* pa = &a;//0x0012ff40 pa是指针变量,用来存放地址,也得申请4(8)个字节的空间//二级指针int** ppa = &pa;//0x0012ff44printf("%p",*ppa);//得到的是paprintf("%d",**ppa);//得到的是areturn 0;
}

 画图表示: 

 解释:int* pa = &a将变量a的地址存放到指针变量pa中去,*表示pa是指针,int说明pa指向的变量是int类型,此时的pa是一个一级指针;int** ppa = &pa,取出指针变量pa的地址,存放到指针变量ppa当中去,*表示ppa是指针,int*则说明ppa指向的pa是int*类型,此时的ppa就是一个二级指针。

  • *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa,pa是地址,用%p打印
  • **ppa 先通过 *ppa 找到 pa ,然后对 pa 再进行解引用操作: *pa ,那么找到的就是a了。

六、指针数组

指针数组是数组还是指针呢?答案是数组,指针数组指的是存放指针的数组,我们观察以下代码具体了解。

#include<stdio.h>
int main()
{int a = 10;int b = 20;int c = 30;int* arr[] = { &a,&b,&c };int i = 0;for (i = 0; i < 3; i++){printf("%d ", *(arr[i])); //对数组的元素解引用操作}return 0;
}


☃️ 以上就是初阶指针部分的详细内容,创作不易,还请各位多加关注、点赞、收藏,感谢支持~ 

相关文章:

【C语言】 详谈指针

☃️内容专栏&#xff1a;【C语言】初阶部分 ☃️本文概括&#xff1a;继初识C语言&#xff0c;对C语言指针初阶部分进行归纳与总结。 ☃️本文作者&#xff1a;花香碟自来_ ☃️发布时间&#xff1a;2023.2.17 目录 一、指针和指针类型 1.1 指针 1.2 指针类型 其一&#x…...

内网渗透(三十八)之横向移动篇-pass the key 密钥传递攻击(PTK)横向攻击

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…...

教你快速学会画动漫人物表情

动漫人物表情画法&#xff0c;3分钟教你快速学会画表情&#xff0c;快来跟我一起零成本学板绘吧&#xff01;咱们的免费板绘系列教程又来啦&#xff0c;今天教大家的板绘技能是什么呢&#xff1f;今天的板绘学习教程来教你如何画动漫女生的表情&#xff01; 板绘动漫女生的表情…...

Qt系列:调用Edge浏览器示例

背景 需要解决以下几个问题 政府项目新浏览器兼容老系统ActiveX控件&#xff0c;Qt WebEngineView没有直接的实现方案&#xff0c;需要利用Qt的ActiveX兼容模块与浏览器往返多次交互Qt ActiveX未实现COM事件通知官方Win32示例存在滥用lambda函数的嫌疑&#xff0c;lambda函数…...

内推|香港外企急招ETL工程师!数据分析师+Python开发+运营专家

2月已过半还在找工作&#xff1f;快来看看有没有适合你的岗位&#xff01;01公司&#xff1a;友邦科技 工作地点&#xff1a;成都市高新区OCG国际中心招聘岗位&#xff1a;ETL工程师 15-18k该岗位为香港项目&#xff0c;需要有数仓或者大数据经验。本科IT或数据相关专业&#…...

zlib压缩原理

数据压缩的本质 去除数据中的冗余信息&#xff0c;对于ABABABABABABAB字样的字符串&#xff0c;AB出现了7次&#xff0c;占用14个字节&#xff0c;如果将该字符串编码为7AB&#xff0c;只占用3个字节。 为什么需要对数据压缩 数据需要存储或者传输&#xff0c;为了节省磁盘空…...

论文阅读笔记《DEEP GRAPH MATCHING CONSENSUS》

核心思想 本文提出一种基于图神经网络的图匹配方法&#xff0c;首先利用节点相似度构建初始的匹配关系&#xff0c;然后利用局部的一致性对初始的匹配关系进行迭代优化&#xff0c;不断筛除误匹配点&#xff0c;得到最终的匹配结果。本文还提出几种措施来降低计算复杂度&#x…...

华为OD机试题 - 开放日活动(JavaScript)

最近更新的博客 2023新华为OD机试题 - 斗地主(JavaScript)2023新华为OD机试题 - 箱子之形摆放(JavaScript)2023新华为OD机试题 - 考古学家(JavaScript)2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)2023新华为OD机试题 - 最多等和不相交连续子序列(JavaScri…...

(考研湖科大教书匠计算机网络)第四章网络层-第八节:网际控制报文协议ICMP

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;网际控制报文协议ICMP&#xff08;1&#xff09;ICMP差错报告报文A&#xff1a;终点不可达B&#xff1a;源点抑制C&#xff1a;时间超过D&#xff…...

华为OD机试 - GPU 调度 | 备考思路,刷题要点,答疑 【新解法】

最近更新的博客 【新解法】华为OD机试 - 关联子串 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 停车场最大距离 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试…...

华为OD机试题 - 任务总执行时长(JavaScript)

最近更新的博客 2023新华为OD机试题 - 斗地主(JavaScript)2023新华为OD机试题 - 箱子之形摆放(JavaScript)2023新华为OD机试题 - 考古学家(JavaScript)2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)2023新华为OD机试题 - 最多等和不相交连续子序列(JavaScri…...

还在想假期去哪玩?直接做一个旅游攻略小程序

憋了几年好不容易解封准备出去散散心,但看着大江南北这么多景点是不是有点让你选择强迫症呢?那就先制作一个旅游攻略小程序看看驴友们的分享吧。...

十四、vue3项目如何使用three.js

近期在开发过程中&#xff0c;因为项目已经接近尾声&#xff0c;就需要对项目中的数据进行整合&#xff0c;而数据看板不失为一个比较直观的展现形式。在数据看板中3D的展现形式是比较流行的展现形式&#xff0c;那么如何在项目引入一个大的场景&#xff0c;并且能够和后台发生…...

python 向excel表中添加新的sheet页或者向旧sheet中写入数据

import xlwt import xlrd from xlutils.copy import copy import os import numpy as np import pandas as pd class Excel_Add_Sheet():def save_table(self, table, file_name):# 保存表table.save(file_name)def add_new_sheet(self, file_name, sheet_name, titleNone):&q…...

RPC-grpc实践

参考&#xff1a;https://developer.aliyun.com/article/1152352?spma2c6h.12873639.article-detail.33.344f6446zEnbRi&scm20140722.ID_communityarticle1152352._.ID_communityarticle1152352-OR_rec-V_1 参考&#xff1a;https://onejson.blog.csdn.net/article/detai…...

JavaEE——MyBatis配置文件的详细介绍

简单介绍&#xff1a; 需要我们编写的配置文件主要有三个&#xff0c;分别是核心配置文件&#xff08;mybatis-config.xml&#xff09;&#xff0c;数据库连接信息文件&#xff08;db.properties&#xff09;&#xff0c;SQL语句映射文件&#xff08;Mappers&#xff09;&…...

bwmarrin/snowflake生成ID重复问题排查记录

现象 某日&#xff0c;运营反馈&#xff0c;在某个时间区间丢失了一段日志&#xff0c;让看看是什么问题。 排查 查看项目日志有无错误 发现项目日志有报错信息Error 1062 Duplicate entry 149059529550598144 for key PRIMARY,很显然&#xff0c;问题在此&#xff0c;数据库…...

操作系统题目收录(十)

1、在存储管理中&#xff0c;采用覆盖与交换技术的目的是&#xff08;&#xff09;。 A&#xff1a;节省主存空间B&#xff1a;物理上扩充主存容量C&#xff1a;提高CPU效率D&#xff1a;实现主存共享 解析 覆盖和交换的提出就是为了解决主存空间不足的问题&#xff0c;但不…...

IOS 自动化测试环境搭建

购买MacPDD 比TB JD 便宜500&#xff0c;下单安装homebrew/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装npm cnpmbrew install node; npm install -g cnpm --registryhttps://registry.npm.taobao.org;安装类似Andro…...

系统设计原则

系统设计原则 好的系统是迭代出来的。先解决核心问题&#xff0c;预测未来可能出现的问题&#xff0c;对现有的问题有方案&#xff0c;对未来的问题有预案。不是一上来就按1亿用户量设计&#xff0c;也不要过度复杂化系统。 业务千变万化&#xff0c;技术层出不穷&#xff0c…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...