【C语言】走进指针世界(下卷)

news2025/3/16 3:46:41

前言

在“走进指针世界(上卷)”中,我们已经说过:什么是指针、内存和地址,指针的使用、声明、初始化,取地址运算符、解引用运算符以及这两者关系,还有指针赋值。

在正式使用指针进行各种代码的编写之前,在这篇“走进指针世界(下卷)”里,让我们再了解一些指针的重要的前置知识吧。

指针变量的大小

指针变量有大小吗? 答案是有的。我们知道,sizeof是一个操作符, 其作用是返回一个对象或类型所占的内存字节数。就像整型变量、字符型变量等可以用sizeof计算大小一样,指针变量也可以这样计算大小:

#include<stdio.h>

int main()
{
	int a = 10;
	int* p = &a;
	printf("%zd\n", sizeof(p));
	return 0;
}

在vs2022的x86(32位环境)下我们可以得出这样的运行结果:

如果改成x64(64位环境),就是这样的运行结果:

 所以我们知道指针变量p的大小就是4或8个字节。

指针变量大小与指向类型的关系:

p是指向整型变量的指针变量,那指向字符型变量的指针变量有多大呢?我们可以再用同样的方式进行观察:

char a = 'a';
char* p = &a;
printf("%zd\n", sizeof(p));
return 0;

x86(32位环境)下结果:

x64(64位环境)下结果:

可以看到指向字符型变量的指针变量的大小同样是4或8个字节。我们可以继续去观察指向其他类型变量的指针变量的大小,最终会发现都是4或8个字节(取决于环境)

为什么呢?

明白这个问题我们必须知道地址是怎么产生的。

计算机中的编址,是通过硬件设计完成的。

计算机中有很多的硬件单元,硬件单元之间互相协同工作,而协同工作需要相互之间能够进行数据传递。硬件之间相互独立,它们的通信方式是用“线”连起来。CPU和内存之间有大量的数据交互,所以这两者也用线连起来。

32位机器有32根地址总线,每根线只有两态,表示为0或1(电脉冲有无),那么一根线可以表示两种含义,32根线就可以表示2^32种含义,每种含义可以表示一个地址。

既然把32根地址线产生的2进制序列当作一个地址,那么一个地址就是32个bit位,需要4个字节来存储。所以,指针变量的大小就是4个字节。 

在这个分析的过程中,我们可以看出,指针变量的大小与该指针指向的数据类型确实是无关的,只与是32位环境还是64位环境有关。

指针变量类型的意义

既然指针变量的大小都是4或8个字节,那么你可能会好奇指针变量类型的意义在哪呢?现在我们就来了解一下指针变量类型的意义。

对于解引用的意义:

第一个方面的意义在于解引用,指针类型的意义决定了在对指针解引用时有多大的权限,或者说一次能操作几个字节

*pa=0之后: 

从内存窗口我们可以看出,在对指向int类型的指针变量pa解引用并赋值0时,我们把4个字节(00为一个字节)都该为了0。

如果将同样的动作施加于一个指向char类型的指针变量,会发生什么?

*pa=0之后:  

可以看到,我们只能操作一个字节。

 所以当指针变量指向的类型不同,即指针变量的类型也不同时,解引用的权限可能是不同的。

对于指针加减整数的意义:

指针变量的类型还决定了指针加减一个整数时,实际移动的字节数。或者通俗点说,指针向前或向后走一步有多大距离。

我们在vs的x86下,用%p打印观察地址。发现同一个整型变量,我们用两个不同类型的指针存储它的地址,在加1后地址的变化不相同。我们知道一个内存单元为1个字节,每个字节有自己的编号即地址,所以pa+1加了4个字节,而pc+1加了1个字节。

其实,pa+1时,加的并不是整数1,而是1*sizeof(int),pc+1时,加的是1*sizeof(char)。 

void*指针

有一种特殊的指针类型,void*指针,也就是无具体类型的指针,也叫泛型指针。

这种指针有其优缺点。

优点: 

它的优点就是既然是泛型指针,在接收一个地址的时候无需局限于某个类型的地址,可以把任意类型数据的地址交给它。比如下面这个代码是合法的:

int a = 10;
void* p = &a;

当我们遇到不知道具体类型的地址又需要用指针存储时,void*指针就可以派上用场。

缺点:

但是它也有自己的缺点,就是无法直接进行指针的加减整

数运算和解引用运算,因为它不知道要操作几个字节。

int a = 10;
void* p = &a;
printf("%d\n", *p);//会报错

const修饰指针

有时,我们不希望指针指向的内容被修改,那么我们就可以使用const对其进行修饰。

还记得const的用法吗?

int a = 100;
a = 200;

在这个代码中,我们把a的值改变了。

​
const int a = 100;
a = 200;//会报错

而我们用const修饰变量a时,a变成了“常变量”,本质上还是个变量,但是不能被修改。

那么现在我们再看一个代码:

我们用const修饰变量n的声明时,我们本意是希望n的值不会被修改,而通过指针我们却间接改掉了变量n的值,那么我们怎样才能达到我们的预期呢?

 

当我们在指针变量p的声明时用cconst进行修饰,就无法再通过刚才的方式修改n的值,而是会报错了。

const与*的前后关系

 在声明一个指针变量并想要用const进行修饰时,我们需要注意的一点是const和*的先后关系。因为当const放在*前面时,无法被修改的是指针指向的内容,当const放在*后面时,无法改变的是指针的指向:

注意,const放在*前面时,在int前还是后都是一样的效果:

 

而当const放在*后面时,才会有根本的改变:

还有一种情况,当我们在*的前后都放上const,那就变成了指向和指向的内容都无法修改:

 

总之,可以根据我们不希望被修改的内容来决定const的用法,并且在需要使用const的时候不要吝啬使用,因为它可以在我们不小心修改了不应该修改的内容时及时给出警告。 

那么,到此为止,“走进指针世界”就结束了,后面我还会持续更新指针相关的更多内容,希望大家发现错误可以向我指正^_^

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

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

相关文章

光缆车间可视化 | 智能制造新科技

光缆车间可视化系统实时监控生产流程、设备状态和质量检测数据&#xff0c;帮助管理人员及时发现并解决问题&#xff0c;提高生产效率和产品质量。

研发机构大数据迁移如何保障敏感数据不泄露

随着云计算和大数据技术的飞速进步&#xff0c;越来越多的企业正试图通过数据迁移来提升IT基础设施的效率&#xff0c;减少成本&#xff0c;并增强业务的灵活性。但是&#xff0c;这一过程并非没有它的挑战&#xff0c;尤其是在数据安全方面。数据在转移过程中可能会遭遇黑客攻…

已有yarn集群部署spark

已有yarn集群的情况下&#xff0c;部署spark只需要部署客户端。 一、前提条件 已部署yarn集群&#xff0c;部署方式参考&#xff1a;https://blog.csdn.net/weixin_39750084/article/details/136750613?spm1001.2014.3001.5502&#xff0c;我部署的hadoop版本是3.3.6已安装j…

第86天:代码审计-PHP项目TP框架安全写法1day利用0day分析

案例一&#xff1a; 利用框架漏洞-TP3框架-SQL注入&Demo&YxtCMF 首先先查询thinkphp的版本 去寻找版本漏洞: Thinkphp3.2.3及以下版本漏洞整理_thinkphp3.2.3漏洞-CSDN博客 去查这个exp注入 这里的利用条件是必须有find方法&#xff0c;并且where后面的参数是数组 …

长效IP和短效IP的使用指南分享

随着网络技术的发展&#xff0c;代理IP已经成为许多人在网络活动中不可或缺的工具。 代理IP不仅有助于保护用户的真实IP地址&#xff0c;保护用户的使用隐私&#xff0c;还可以帮助用户提升网络访问的速度等。 然而&#xff0c;在挑选代理IP时&#xff0c;用户常常会面临一个…

【Basic】Upload-Labs-Linux

文章目录 前言Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16解题感悟 前言 美好的一天从刷题开始 Pass-01 我淦20道题&#xff1f;&#xff1f;&#xff1f;一道一道来吧 先看第一道题 先在home里搞一…

基于open3d对kitti数据集检测结果可视化

前言 KITTI数据集是自动驾驶和计算机视觉领域中一个广泛使用的基准数据集&#xff0c;它提供了丰富的传感器数据&#xff0c;包括激光雷达、相机和GPS等。Open3D是一个功能强大的3D数据处理和可视化库&#xff0c;支持多种3D数据格式。本文将介绍如何使用Open3D对KITTI数据集的…

9.Docker网络

文章目录 1、Docker网络简介2、常用基本命令3、网络模式对比举例3.1、bridge模式3.2、host模式3.3、none模式3.4、container模式3.5、自定义网络 1、Docker网络简介 作用&#xff1a; 容器间的互联和通信以及端口映射容器IP变动时候可以通过服务名直接进行网络通信而不受到影…

PY32F003+RTL8710(AT) 实现获取天气情况

一、RTL8710主要AT指令 1、ATSR&#xff1a;模块重启 2、ATSE1&#xff1a;开启回显 3、ATPW1&#xff1a;station模式 4、ATPNssid,password,,&#xff1a;连接到AP 5、ATPK1&#xff1a;设置自动接收 6、ATPC0,v1.yiketianqi.com,80&#xff1a;与网站建立TCP连接 7、ATPT125…

USART串口通信(stm32)

一、串口通信 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统 通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发 STM32F103C8T6 USART资源&#xff1a; USART1、 USART2、 USART3 自带波特率发生器&…

基于Android studio 使用SQLite数据库完成登录注册功能——保姆级教程

&#x1f345;文章末尾有获取完整项目源码方式&#x1f345; 点击快捷传送地址&#xff1a; 保姆级教学——制作登陆注册功能页面 目录 一、准备工作 二、创建相关文件 三、页面布局 四、DabaHelper帮助类的编写 五、RegisterActivity注册页面 六、LoginActivity登录页面…

【Kafka】消息的顺序性、可靠性、幂等性

目录 消息顺序性消息可靠性生产者丢失消息消费者丢失消息Kafka丢失消息 消息幂等性 消息顺序性 消息追加到partition尾部&#xff0c;单个partition是有序的&#xff0c;但多个partition如何进行有序的获取一些消息&#xff1f; 解决方案 一个topic只设置一个partition&…

深入了解Socket套接字

目录 一、引入&#x1f64c; 1、概念 &#x1f389; 2、分类&#x1f389; Socket 套接字主要针对传输层协议分为流套接字、数据报套接字、原始套接字&#xff08;了解即可&#xff09;三类。 1&#xff09;流套接字&#xff1a;使用传输层TCP协议 2&#xff09;数据报套…

基于Matlab使用BP神经网络进行电力系统短期负荷预测

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 电力系统的短期负荷预测对于电力调度和能源管理具有至关重要的作用。通过准确地预测电力负荷&…

代码随想录算法训练营第三十七天|435. 无重叠区间、763.划分字母区间、56. 合并区间、738.单调递增的数字、968.监控二叉树

435. 无重叠区间 文档讲解&#xff1a;代码随想录 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 本道题与上个题目相似&#xff0c;都是求重叠区间 统计重叠区间的个数&#xff0c;减去重叠区间的个数就是无重叠区间了 主要就是为了让区间尽可能的重叠。&a…

HTML5新特性、JS【初识JS 、JS核心语法】--学习JavaEE的day47

day47 HTML5新特性 定义文档类型 在文件的开头总是会有一个标签 语言文档类型声明方式html4<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">html5<!DOCTYPE html> 新增语义化标签 理解&…

SpringBoot + MybatisPlus

SpringBoot MybatisPlus 整合记录 1. 硬件软件基本信息2. 相关链接3. 通过idea快速生成一个Springboot项目4. 启动报错问题解决问题一&#xff1a;Springboot启动的时候报错提示 “没有符合条件的Bean关于Mapper类型”问题二&#xff1a;启动的时候提示需要一个Bean&#xff0…

民国漫画杂志《时代漫画》第16期.PDF

时代漫画16.PDF: https://url03.ctfile.com/f/1779803-1248612470-6a05f0?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络&#xff01;

Jenkins在windows上进行安装

今天为了实现jmeter接口测试脚本的持续性集成安装了jenkins&#xff0c;主要记录jenkins的安装和端口的修改。 前提条件&#xff1a;安装了jdk&#xff0c;我本机安装的jdk1.8。 1.下载jenkins安装包 安装jenkins我们需要先下载安装包&#xff0c;可以通过下面的链接进行下载&a…

深入理解内联函数(C语言)

目录 1.什么是内联函数2.内联函数与宏3.编译器对内联函数的处理4.参考文献 1.什么是内联函数 很多人都会知道&#xff0c;可以将比较小的函数写成内联函数的形式&#xff0c;这样会节省函数调用的开销&#xff0c;具体是什么样的开销呢&#xff1f; 一个函数在执行过程中&…