深入了解指针(一)

news2025/2/26 6:01:50

前言

指针可是数据结构的基础,其内容及重要又繁多,之前没有时间整理出来,现在放假了怎么说也要写一个,既是对前面的总结和梳理,也可以用来以后的查找知识,ok,废话不多,直接启动。

指针是什么

指针是C语言中的一种特殊数据类型,它存储了一个变量的内存地址。通过指针,我们可以直接访问和修改该内存地址上存储的值。指针变量本身也有自己的存储地址,而指向指针变量的存储地址就被称为指针的指针,即二级指针。多级指针的定义就是定义时使用多个"*"号。

1内存和地址

1.1内存

我们知道你的代码中的变量常量都是放在内存中的,我们电脑大多是4g或8g内存,这些内存空间被平均分了许多份,每份大小是1个字节

下面是常见的内存大小单位以及换算

我们可以把整个内存当成一个酒店,每个空间当作一个房间,那么每个房间的门牌号就是地址,我把地址告诉你了,你自然就能找到那个房间了。而在C语言中地址就是指针。

1.2地址的写法

我们知道你电脑cpu和内存要互相协同⼯作的。所谓的协同,⾄少相互之间要能够进⾏数据传递。那么如何通信呢?答案很简单,⽤"线"连起来,我们今天关⼼⼀组线,叫做地址总线。

我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表⽰0,1【电脉冲有⽆】,那么
⼀根线,就能表⽰2种含义,2根线就能表⽰4种含义,依次类推。32根地址线,就能表⽰2^32种含
义,每⼀种含义都代表⼀个地址。如此一来每个字节大小的空间就被编好地址了。
地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传⼊
CPU内。
当然了,为了书方便我们写地址是以16进制写的,对32位机器如果某个空间地址是
10000000 10000000 10000000 10000000
换算成16进制就是0XF0 F0 F0 F0       前面的0X表示这个数是16进制,且字母大写
取地址操作符(&)
理解了内存和地址的关系,我们再回到C语⾔,在C语⾔中创建变量其实就是向内存申请空间,⽐如:
上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都
很明显他们里面存放的值分别是0a    00  00  00,用小端换算成10进制就是10
那我们如何能得到a的地址呢? 用到操作符&
当然了这里的地址是4个地址中最小的那个,你可以理解为从这个地址开始向后4个字节都是a的空间,于是乎我们顺藤摸瓜就能找到另外三个了
那我们通过取地址操作符(&)拿到的地址是⼀个数值,⽐如:0x006FFD70,这个数值有时候也是需要

2指针变量和地址

2.1取地址操作符&和指针变量

将指针存储起来,可以⽅便后期再使⽤的,那我们把这样的地址值存放在哪⾥呢?答案是:指针变量中,用什么方法呢?答案是取地址操作符
#include<stdio.h>
int main()
{
    int a = 10;
    int* p = &a;
    return 0;
}
指针变量也是⼀种变量, 这种变量就是⽤来存放地址的,存放在指针变量中的值都会理解为地址。
指针变量的类型:对应数据类型加上一个*
int对应int*
char对应char*
double对应double*
以此类推
可以理解为*是在说明他是个指针,而前面的int则说明它指向的地址里的数据是int类型,这个地址的值就被存到这个指针变量里了

2.2解引用操作符*

我们将地址保存起来,未来是要使⽤的,那怎么使⽤呢?
这里就要用到解引用操作符*了
和明显我们通过*p找到了a并且打印了出来,
这里我们通过指针p修改了a的值
可能有同学会觉得麻烦,感觉不如直接打印a或者修改a, 但以后函数的传值与传址就会明白了

2.3 指针变量的⼤⼩

前⾯的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后
是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4
个字节才能存储。
如果指针变量是⽤来存放地址的,那么指针变的⼤⼩就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要
8个字节的空间,指针变的⼤⼩就是8个字节
x64环境下的
x86环境下
结论:
32位平台下地址是32个bit位,指针变量⼤⼩是4个字节
64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。

3. 指针变量类型的意义

3.1 指针的解引⽤

x会将a的4个字节全部改为0,y只是将b的第⼀个字节改为0。

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。
⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节。

3.2void* 指针

在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为⽆具体类型的指针(或者叫泛型指
针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进
⾏指针的+-整数和解引⽤的运算。
int main()
{
    int a = 10;
    void* p = &a;
    *p = 0;
    p++;
    return 0;
}
⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以
实现泛型编程的效果。使得⼀个函数来处理多种类型的数据,

4. const修饰指针

4.1 const修饰指针变量

int main()
{
    int a = 10;
    const int* p = &a;
    *p = 5;
    return 0;
}
这时无法通过*p修改a的值
这时不能改变p的值
但是你可以通过二级指针的方法绕过去,可事实上不该这样做,因为他既然被const修饰了就说明写他的人不希望它被改变,
int main()
{
    int a = 10;
    int b = 5;
     int* const p = &a;
     int** b = &p;
     int*x = &b;
     b = &x;
    return 0;
}
结论:const修饰指针变量的时候
const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本⾝的内容可变。
const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指
向的内容,可以通过指针改变

5. 指针运算

指针的基本运算有三种,分别是:
指针+- 整数
指针-指针
指针的关系运算

5.1 指针+- 整数

因为数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸⽠就能找到后⾯的所有元素。

5.2 指针-指针

我们通过这个实现了strlen函数
//指针的关系运算
#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的⼤⼩⽐较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

5.3 指针的关系运算

//指针的关系运算
#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的⼤⼩⽐较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

6. 野指针

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

6.1 野指针成因

1. 指针未初始化

# include <stdio.h>
int main ()
{
int *p; // 局部变量指针未初始化,默认为随机值
*p = 20 ;
return 0 ;
}

2. 指针越界访问

 

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

3. 指针指向的空间释放

#include <stdio.h>
int* test()
{
 int n = 100;
 return &n;
}
int main()
{
 int*p = test();
 printf("%d\n", *p);
 return 0;
}

 6.2 如何规避野指针

6.2.1 指针初始化

如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL.
NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址
会报错。

6.2.2 ⼩⼼指针越界

6.2.3 指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性

当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的
时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问,
同时使⽤指针之前可以判断指针是否为NULL

6.2.4 避免返回局部变量的地址

如造成野指针的第3个例⼦,不要返回局部变量的地址。

7. assert断⾔

assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报
错终⽌运⾏。这个宏常常被称为“断⾔”。
assert(p != NULL );
上⾯代码在程序运⾏到这⼀⾏语句时,验证变量 p 是否等于 NULL 。如果确实不等于 NULL ,程序
继续运⾏,否则就会终⽌运⾏,并且给出报错信息提⽰。
这个可以很好的处理野指针的问题
最后留个思考问题,函数传值与传址的区别,这就是我们为什么要学指针的一个原因。

总结

ok,今天的内容包括以下这些

1 .内存和地址
2. 指针变量和地址
3. 指针变量类型的意义
4. const修饰指针
5. 指针运算
6. 野指针
7. assert断⾔
也是相当多了,但关于指针我可能要写4篇博客吧,因为它真的很重要而且有难度,今天的算是把基础讲的差不多了,那么如果你觉得对你有帮助的话就点个免费的赞支持一下吧,谢谢!

 

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

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

相关文章

网络文件共享服务 FTP

一、存储类型 存储类型分为三种 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS 存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN&#xff08;可以使用空间&#xff0c;管理也是你来管理&#xff09; 网络附加存储&#xff1a;Network…

kafka系列(二)

本章承接kafka一内容&#xff0c;文章在本人博客主页都有&#xff0c;可以自行点击浏览。 幂等性 请求执行多次&#xff0c;但执行的结果是一致的。 如果&#xff0c;某个系统是不具备幂等性的&#xff0c;如果用户重复提交了某个表格&#xff0c;就可能会造成不良影响。例如…

SecureCRT7中文版安装资源,一键安装

SecureCRT 7 是一款功能强大的终端仿真软件&#xff0c;主要用于安全地远程访问和管理各种网络设备和服务器。 它支持多种协议&#xff0c;如 SSH、Telnet、Rlogin 等&#xff0c;可以连接到不同类型的设备&#xff0c;包括 Unix/Linux 服务器、网络设备、虚拟机等。通过使用 …

黑马程序员JavaWeb开发|案例:tlias智能学习辅助系统(5)登录认证

指路&#xff08;1&#xff09;&#xff08;2&#xff09;&#xff08;3&#xff09;&#xff08;4&#xff09;&#x1f447; 黑马程序员JavaWeb开发|案例&#xff1a;tlias智能学习辅助系统&#xff08;1&#xff09;准备工作、部门管理_tlias智能学习辅助系统的需求分析-CS…

C++的构造析构函数

前言 本篇文章介绍C的构造函数和虚构函数 写在前面 因为介绍构造函数基本都会设计虚函数和虚基类的使用&#xff0c;可以参考之前的文章&#xff1a; C中的虚函数 C的虚基类 构造函数 每个类都分别定义了它的对象被初始化的方式&#xff0c;类通过一个或几个特殊的成员函数…

蓝牙运动耳机哪款好用?运动用哪种耳机好?2024运动蓝牙耳机推荐

​户外活动、健身运动还是激烈跑步&#xff0c;一款出色的运动耳机能够提升整体运动体验。这些耳机不仅具备出色的防汗和稳定佩戴性能&#xff0c;更通过强劲音质为你注入动力。让我们一同探索几款在各种运动场景中脱颖而出的运动耳机吧。 1.南卡开放式耳机&#xff08;00压&a…

二阶贝塞尔曲线生成弧线

概述 本文分享一个二阶贝塞尔曲线曲线生成弧线的算法。 效果 实现 1. 封装方法 class ArcLine {constructor(from, to, num 100) {this.from from;this.to to;this.num num;return this.getPointList();}getPointList() {const { from, to } thisconst ctrlPoint thi…

车灯芯片 H5028L 12V 24V 48V 60V 72V 80V 100V转9V 12V 高低亮 远近光恒流芯片

车灯芯片是车辆照明系统中的重要组成部分&#xff0c;通常采用LED&#xff08;发光二极管&#xff09;技术。以下是车灯芯片的工作原理&#xff1a; LED原理&#xff1a; 车灯芯片主要采用LED作为光源。LED是一种半导体器件&#xff0c;当电流通过LED芯片时&#xff0c;电子和…

(C语言)用函数指针数组实现计算器

一、运算结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现目录函数&#xff1b; void menum() {//打印目录&#xff1b;printf("***********************************************\n");printf("***…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(十二)

购物车相关 1.添加购物车1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码开发1.2.1 DTO设计1.2.2 Controller层1.2.3 Service层接口1.2.4 Service层实现类1.2.5 Mapper层 2. 查看购物车2.1 需求分析和设计2.1.1 产品原型2.1.2 接口设计 2.2 代码开发2.2.…

安科瑞电动汽车充电桩运维平台 ——安科瑞 顾烊宇

充电桩其功能类似于加油站里面的加油机&#xff0c;可以固定在地面或墙壁&#xff0c;安装于公共建筑&#xff08;公共楼宇、商场、公共停车场等&#xff09;和居民小区停车场或充电站内&#xff0c;可以根据不同的电压等级为各种型号的电动汽车充电。充电桩的输入端与交流电网…

HCIA 网络基础:

应用层 抽象语言-->编码 表示层 编码-->二进制 会话层 建立会话&#xff0c;提供绘画地址。 应用于程序内部进行区分&#xff0c;没有统一标准 上三层主要是软件层面&#xff08;应用 程序处理数据&#xff09; 下四层主要负责数据传输 传输层 端口号 分段 &#xff…

PHP+MySQL组合开发:微信小程序万能建站源码系统 附带完整的搭建教程

随着移动互联网的快速发展&#xff0c;微信小程序已成为企业进行移动营销的重要工具。然而&#xff0c;对于许多中小企业和个人开发者来说&#xff0c;开发一个功能完善、用户体验良好的小程序是一项复杂的任务。罗峰给大家分享一款微信小程序万能建站源码系统。该系统采用PHPM…

C++设计模式-- 2.代理模式 和 外观模式

文章目录 代理模式外观模式角色和职责代码演示一&#xff1a;代码演示二&#xff1a;外观模式适用场景 代理模式 代理模式的定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合 或不能直接引用另一个对象&#xff0c;而代…

Controller层自定义注解拦截request请求校验

一、背景 笔者工作中遇到一个需求&#xff0c;需要开发一个注解&#xff0c;放在controller层的类或者方法上&#xff0c;用以校验请求参数中(不管是url还是body体内&#xff0c;都要检查&#xff0c;有token参数&#xff0c;且符合校验规则就放行)是否传了一个token的参数&am…

旧衣回收小程序搭建:降低企业成本,提高回收效率!

在人们环保意识提升下&#xff0c;旧衣回收行业受到了大众的关注&#xff0c;同时旧衣回收具有门槛低、利润大的优势。在我国&#xff0c;回收行业不仅帮助普通人就业获利&#xff0c;还对环保做出了较大贡献。因此&#xff0c;旧衣回收行业成为了当下的热门商业模式&#xff0…

C#,入门教程(19)——循环语句(for,while,foreach)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(18)——分支语句&#xff08;switch-case&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/124039953 一、for循环 当老师进入教室&#xff0c;从门口开始分别按行、列点名&#xff0c;看看哪位翘课&…

详细介绍如何使用T5实现文本摘要:微调和构建 Gradio 应用程序-含完整源码

对高效文本摘要的需求从未如此迫切。无论您是正在处理冗长研究论文的学生还是浏览新闻文章的专业人士,快速提取关键见解的能力都是非常宝贵的。T5 是一种因多项 NLP 任务而闻名的预训练语言模型,擅长文本摘要。使用 T5 的文本摘要与 Hugging Face API 是无缝的。然而,对 T5 …

二、基础篇 vue计算属性和侦听器

计算属性 模板内的表达式非常便利&#xff0c;但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如&#xff1a; <div id"example">{{ message.split().reverse().join() }} </div> 在这个地方&#xff0c;模板不…

【松叶漫话】来聊聊ChatGPT 和文心一言吧

两大AI助手的较量 在当今信息技术飞速发展的时代&#xff0c;人工智能助手成为我们生活中不可或缺的一部分。ChatGPT和文心一言作为两大代表性的AI助手&#xff0c;在智能回复、语言准确性、知识库丰富度等方面各有千秋。本文将就这两位AI助手的特点进行深入比较&#xff0c;为…