32 C 语言指针的长度与运算(指针加减整数、指针自增自减、同类型指针相减、指针的比较运算)

目录

1 指针的长度

2 指针与整数的加减运算

3 指针自增与自减

4 同类型指针相减

5 指针的比较运算

6 测试题 


1 指针的长度

        在 C 语言中,sizeof 运算符可以用来计算指针的长度。指针的长度实际上与指针所指向的数据类型无关,而是与系统的位数(即系统架构)有关。具体来说:

  • 32 位系统:无论指针指向什么类型的数据(如 int、char、float 等),指针的长度都是 4 个字节(32 位)。
  • 64 位系统:无论指针指向什么类型的数据,指针的长度都是 8 个字节(64 位)。

        下面是一个示例,展示了如何使用 sizeof 运算符来计算不同类型指针的长度:

#include <stdio.h>int main()
{int *int_ptr;char *char_ptr;float *float_ptr;double *double_ptr;printf("int 指针的长度: %zu 字节\n", sizeof(int_ptr));printf("char 指针的长度: %zu 字节\n", sizeof(char_ptr));printf("float 指针的长度: %zu 字节\n", sizeof(float_ptr));printf("double 指针的长度: %zu 字节\n", sizeof(double_ptr));return 0;
}

        在 32 位系统上运行上述代码,输出可能是:

int 指针的长度: 4 字节
char 指针的长度: 4 字节
float 指针的长度: 4 字节
double 指针的长度: 4 字节

        在 64 位系统上运行上述代码,输出可能是:

int 指针的长度: 8 字节
char 指针的长度: 8 字节
float 指针的长度: 8 字节
double 指针的长度: 8 字节

结论:

  • 指针的长度与系统架构有关在 32 位系统中,所有指针的长度都是 4 个字节;在 64 位系统中,所有指针的长度都是 8 个字节
  • 指针的长度与指向的数据类型无关:无论指针指向 int、char、float 还是 double,指针本身的长度是固定的,由系统的位数决定。

2 指针与整数的加减运算

        指针与整数的加减运算表示指针所指向的内存地址的移动。具体来说:

  • 加法运算:指针加一个整数表示指针向后移动
  • 减法运算:指针减一个整数表示指针向前移动

        指针移动的步长与指针指向的数据类型有关。每移动一个单位,指针会移动相应数据类型所占的字节数。例如:

  • 如果指针指向 int 类型的数据,int 通常占用 4 个字节,那么指针加 1 会向后移动 4 个字节,指针减 2 会向前移动 8 个字节。
  • 如果指针指向 char 类型的数据,char 通常占用 1 个字节,那么指针加 1 会向后移动 1 个字节,指针减 2 会向前移动 2 个字节。

        数组的元素在内存中是连续存储的,因此通过数组元素可以很好地演示指针加减整数的情况。以下是一个示例:

#include <stdio.h>int main()
{// 创建一个包含 5 个整数的数组int nums[] = {10, 20, 30, 40, 50};// 创建一个指针并将其初始化为数组第一个元素的地址int *ptr = &nums[0];// int *ptr = nums; 或者直接指向数组名 和上面等价// 打印指针的地址和指针所指向的值printf("初始状态: ptr=%p, *ptr=%d \n", (void *)ptr, *ptr);// 指针加 3,指针指向 int 类型,每个 int 占 4 个字节// 因此,指针会向后移动 3 * 4 = 12 个字节ptr += 3;printf("指针加 3 后: ptr=%p, *ptr=%d \n", (void *)ptr, *ptr);// 指针减 2,指针会向前移动 2 * 4 = 8 个字节ptr -= 2;printf("指针减 2 后: ptr=%p, *ptr=%d \n", (void *)ptr, *ptr);return 0;
}

        输出结果如下所示:


3 指针自增与自减

        指针的自增和自减本质上是通过加减整数来实现的。自增会使指针向后移动,自减会使指针向前移动移动的步长与指针指向的数据类型有关。每移动一个单位,指针会移动相应数据类型所占的字节数。例如,如果指针指向 short 类型的数据,short 通常占用 2 个字节,那么指针自增 1 会向后移动 2 个字节,指针自减 1 会向前移动 2 个字节。

#include <stdio.h>int main()
{// 创建数组,元素都是 short 类型,每个元素占据 2 个字节short nums[] = {10, 20, 30, 40, 50};// 定义常量记录数组长度const int len = sizeof(nums) / sizeof(nums[0]); // 5// 利用指针自增遍历数组元素// 创建指针并指向数组第一个元素的地址short *ptr = &nums[0];// short *ptr = nums; 或者直接指向数组名 和上面等价// 循环遍历数组for (int i = 0; i < len; i++){// 打印当前元素的索引、地址和值printf("元素索引:%d, 元素地址:%p, 元素值:%hd \n", i, (void *)ptr, *ptr);// 指针自增,向后移动一个 short 类型的单位(2个字节)ptr++;}printf("\n");// 循环遍历数组,从最后一个元素到第一个元素// 此时指针超出数组界限,需先自减一次for (int i = len - 1; i >= 0; i--){// 指针自减,向前移动一个 short 类型的单位(2个字节)ptr--;// 打印当前元素的索引、地址和值printf("元素索引:%d, 元素地址:%p, 元素值:%hd \n", i, (void *)ptr, *ptr);}return 0;
}

        输出结果如下所示:

        在上述示例中,当第一次循环(正序输出数组元素)结束后,指针 ptr 已经超出了数组的边界,指向了数组最后一个元素之后的位置,如下图所示。因此,在进行第二次循环(倒序输出数组元素)之前,需要先将指针重置为数组最后一个元素的地址,以确保能够正常输出

        可以使用 ptr-- 重置指针:在第一次循环结束后,指针 ptr 超出了数组的边界。可以通过 ptr-- 将指针向前移动一个单位,使其指向数组的最后一个元素。如上述代码中的第二次循环一开始就 使用 ptr-- 重置指针。

        也可以直接重置指针:可以直接将指针 ptr 重新初始化为数组最后一个元素的地址,这样可以确保指针指向正确的起始位置。如下代码所示:

#include <stdio.h>int main()
{// 创建一个包含 5 个 short 类型的数组short nums[] = {10, 20, 30, 40, 50};int n = sizeof(nums) / sizeof(nums[0]); // 计算数组的长度// 创建指针并初始化为数组第一个元素的地址short *ptr = &nums[0];// 正序输出数组元素printf("正序输出数组元素:\n");for (int i = 0; i < n; i++){printf("元素索引:%d, 元素地址:%p, 元素值:%hd \n", i, (void *)ptr, *ptr);ptr++; // 指针自增,向后移动一个 short 类型的单位(2个字节)}printf("\n");// 重置指针,使其指向数组最后一个元素的地址ptr = &nums[n - 1];// 倒序输出数组元素printf("倒序输出数组元素:\n");for (int i = n - 1; i >= 0; i--){printf("元素索引:%d, 元素地址:%p, 元素值:%hd \n", i, (void *)ptr, *ptr);ptr--; // 指针自减,向前移动一个 short 类型的单位(2个字节)}return 0;
}

4 同类型指针相减

        相同类型的指针可以进行减法运算,返回它们之间的距离,即相隔多少个数据单位高位地址减去低位地址,返回的是正值;低位地址减去高位地址,返回的是负值同类型指针相减的结果是一个 ptrdiff_t 类型的数据,ptrdiff_t 是一个带符号的整数,格式输出中对应的格式占位符是 %td

        以下是一个示例,演示了如何使用同类型指针相减来计算它们之间的距离:

#include <stdio.h>int main()
{// 创建一个包含 5 个整数的数组int nums[] = {10, 20, 30, 40, 50};// 创建指针并指向数组第一个元素的地址int *ptr1 = &nums[0];// 创建指针并指向数组第四个元素的地址int *ptr2 = &nums[3];// 打印查看原始内容printf("ptr1地址:%p\n", ptr1);printf("ptr2地址:%p\n", ptr2);// 计算两个指针之间的距离// ptr2 - ptr1 应该等于 3,因为 ptr2 指向第四个元素,ptr1 指向第一个元素printf("ptr2 - ptr1 = %td \n", ptr2 - ptr1); // 输出 3// ptr1 - ptr2 应该等于 -3,因为 ptr1 指向第一个元素,ptr2 指向第四个元素printf("ptr1 - ptr2 = %td \n", ptr1 - ptr2); // 输出 -3// 再连续创建两个变量double d1 = 1.0;double d2 = 2.0;// 创建指针并分别指向 d1 和 d2 的地址double *p1 = &d1;double *p2 = &d2;printf("p1地址:%p\n", p1);printf("p2地址:%p\n", p2);// 计算两个指针之间的距离// p1 - p2 应该等于 1,因为 p1 指向 d1,p2 指向 d2,d1 和 d2 在内存中是相邻的printf("p1 - p2 = %td \n", p1 - p2); // 输出 1// p2 - p1 应该等于 -1,因为 p2 指向 d2,p1 指向 d1,d1 和 d2 在内存中是相邻的printf("p2 - p1 = %td \n", p2 - p1); // 输出 -1return 0;
}

        输出结果如下所示:


5 指针的比较运算

        指针之间可以进行比较运算,如 ==、!=、<、<=、>、>=。这些运算符比较的是指针所指向的内存地址的大小,返回值是 int 类型的整数,1 表示 true,0 表示 false

        以下是一个示例,演示了如何使用指针的比较运算:

#include <stdio.h>int main()
{// 创建一个包含 5 个整数的数组int nums[] = {10, 20, 30, 40, 50};double n = 1.0;// 创建指针并指向数组第一个元素的地址int *ptr1 = &nums[0];// 创建指针并指向数组第四个元素的地址int *ptr2 = &nums[3];// 创建指针也指向数组第一个元素的地址int *ptr3 = &nums[0];// 创建指针指向变量 n 的地址double *ptr4 = &n;// 输出指针指向的地址printf("ptr1=%p\n", (void *)ptr1);printf("ptr2=%p\n", (void *)ptr2);printf("ptr3=%p\n", (void *)ptr3);printf("ptr4=%p\n\n", (void *)ptr4);// 进行比较// 比较 ptr1 和 ptr2 的地址printf("ptr1 > ptr2: %d \n", ptr1 > ptr2); // 比较 ptr1 是否大于 ptr2printf("ptr1 < ptr2: %d \n", ptr1 < ptr2); // 比较 ptr1 是否小于 ptr2// 比较 ptr1 和 ptr3 的地址printf("ptr1 == ptr3: %d \n", ptr1 == ptr3); // 比较 ptr1 是否等于 ptr3// 比较不同类型的指针(ptr4 和 ptr1)// 注意:不同类型的指针进行比较会引发编译器警告printf("ptr4 > ptr1: %d \n", ptr4 > ptr1); // 比较 ptr4 是否大于 ptr1return 0;
}

        注意,不同类型的指针进行比较会引发编译器警告。如下所示:

        输出结果如下所示:


6 测试题 

1. 请写出下面程序的运行结果(64 位操作系统)。

int num = 250;
int *p = &num;
printf("%zu \n", sizeof p);
printf("%zu \n", sizeof *p);

【答案】

        8

        4

【解析】

        sizeof p 是计算指针本身的长度,指针存储的是地址,在 64 位操作系统下,地址占 8 个字节。

        sizeof *p 是计算指针指向的数据的长度,指针 p 指向 int 类型变量 num,int 类型长度是 4 个字节。


2. 请写出下面程序的运行结果。

int arr[] = {10,20,30,40,50};
int *p = arr;  
printf("%d", *(p+1) + *(p+2)); 

【答案】

        50

【解析】

        指针 p 指向数组 arr 的首元素地址

        p+1 得到数组 arr 第二个元素的地址,*(p+1) 得到第二个元素的值 20。

        p+2 得到数组 arr 第三个元素的地址,*(p+2) 得到第三个元素的值 30。

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

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

相关文章

怎么通过AI大模型开发一个网站?

目录 一、提示词与AI输出 二、网站效果 以前不会代码开发&#xff0c;写网站是不可能的事情&#xff0c;现在有了AI&#xff0c;一切都有了可能。以下是我通过通义千问大模型开发的简单网站。 一、提示词与AI输出 提示词1 你是python程序员&#xff0c;我有一个大的需求&am…

Charles(青花瓷)抓取https请求

文章目录 前言Charles&#xff08;青花瓷&#xff09;抓取https请求 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&…

QTreeview model过滤

QTreeview model数据过滤&#xff1a;大小写区分&#xff0c;对列过滤&#xff0c;对子对象过滤 示例&#xff1a; 需要自定义QSortFilterProxyModel, //自定义过滤model mProxyModel new TreeFilterProxyModel(this); //添加treeview当前model mProxyModel->setSource…

re轻松拆分四则运算expression(^从头匹配、(?:xxxx)非捕获组、| 交替运算符联合演习)

与ai对抵聊“算式匹配”&#xff0c;发现^从头匹配、(?:xxxx)非捕获组、| “交替”运算符联合使用的妙处。 (笔记模板由python脚本于2024年09月27日 18:35:32创建&#xff0c;本篇笔记适合喜欢python喜欢正则的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;…

云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 王 峰 | 阿里云智能集团研究员、开源大数据平台负责人 李 钰&#xff5c;阿里云智能集团资深技术专家 范 振&#xff5c;阿里云智能集团高级技术专家 李劲松&#xff5c;阿里云…

Flume入门到实践--Flume的安装与基础概念与安装实战

在当今大数据时代&#xff0c;有效管理和处理海量日志数据对于企业获取洞察和保持运营效率至关重要。为此目的设计的强有力工具之一是 Apache Flume。本文将带您探索Flume&#xff0c;了解其功能、安装方法以及一些实际用例&#xff0c;以展示其在处理日志数据方面的有效性。 …

逻辑回归(中):数学公式学习笔记 LaTeX 版

背景 闲来无事翻了一下之前买的一个机器学习课程及之前记录的网络笔记&#xff0c;发现遇到公式都是截图&#xff0c;甚至是在纸上用笔推导的。重新整理一遍之前逻辑回归函数的学习笔记&#xff0c;主要是为了玩一下 LaTex 语法&#xff0c;写公式挺有意思的。 整理之前三篇笔…

机器学习-SVM

线性感知机分类 支持向量机 线性感知机&#xff08;Perceptron&#xff09; 感知机是线性二值分类器。 注意&#xff1a;什么是线性&#xff1f;线性分割面就是&#xff0c;就是在分割面中&#xff0c;任意两个的连线也在分割面中&#xff0c;这个分割面&#xff0c;就是线…

debian linux 只安装mysql client

查询系统版本 执行cat /etc/os-release 可以看到是debian11 rootservice-headquarters-hg-self-data-report-844ccf78b-6ls7t:/mysql#cat /etc/os-release PRETTY_NAME"Debian GNU/Linux 11 (bullseye)" NAME"Debian GNU/Linux" VERSION_ID"11&quo…

DOM元素导出图片与PDF:多种方案对比与实现

背景 在日常前端开发中&#xff0c;经常会有把页面的 DOM 元素作为 PNG 或者 PDF 下载到本地的需求。例如海报功能&#xff0c;简历导出功能等等。在我们自家的产品「代码小抄」中&#xff0c;就使用了 html2canvas 来实现代码片段导出为图片&#xff1a; 是不是还行&#xff…

【STM32】SPI回顾

一、定义 SPI是Motorola首先提出的全双工四线同步串行外围接口&#xff0c;采用主从模式&#xff08;Master-Slave&#xff09;架构。 二、单机与多机通信 4线SPI器件有四个信号&#xff1a;时钟(SPI CLK, SCLK)、主机输出从机输入(MOSI)、主机输入从机输出(MISO)、片选(CS/N…

简单理解C++在C的基础上的改变

1.C语言的一些不足 我们首先看下面用C语言实现栈 #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int StackDateType; typedef struct Stack {StackDateType* _ps;size_t _size;size_t _capacity; }Stack; void StackInit(Stack* ps) {…

Qt_网络编程

目录 1、Qt的UDP Socket 1.1 用Udp实现服务器 1.2 用Udp实现客户端 2、Qt的TCP Socket 2.1 用Tcp实现服务器 2.2 用Tcp实现客户端 3、Qt的HTTP 3.1使用Qt的HTTP 结语 前言&#xff1a; 网络协议是每个平台都必须遵守的&#xff0c;只是不同的平台所提供的网络API不…

工业缺陷检测——Windows 10本地部署AnomalyGPT工业缺陷检测大模型

0. 引言 在缺陷检测中&#xff0c;由于真实世界样本中的缺陷数据极为稀少&#xff0c;有时在几千甚至几万个样品中才会出现一个缺陷数据。因此&#xff0c;以往的模型只需在正常样本上进行训练&#xff0c;学习正常样品的数据分布。在测试时&#xff0c;需要手动指定阈值来区分…

实现语音合成的三种方法:HTML5 Web Speech 、speak-tts、百度语音合成

1. 使用HTML5 Web Speech API 1.1 使用方法 window.speechSynthesis 是HTML5 Web Speech API的一部分&#xff0c;是浏览器原生提供的文本转语音功能。它允许开发者在网页上通过JavaScript调用&#xff0c;将文本转换为语音进行播放。 https://developer.mozilla.org/zh-CN/d…

渗透测试--文件上传常用绕过方式

文件上传常用绕过方式 1.前端代码&#xff0c;限制只允许上传图片。修改png为php即可绕过前端校验。 2.后端校验Content-Type 校验文件格式 前端修改&#xff0c;抓取上传数据包&#xff0c;并且修改 Content-Type 3.服务端检测&#xff08;目录路径检测&#xff09; 对目…

LMDeploy 量化部署实践

任务 使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat模型封装本地API并与大模型进行一次对话 复现过程 按照教材安装环境。https://github.com/InternLM/Tutorial/blob/camp3/docs/L2/LMDeploy/readme.md 使用LMDeploy部署原版的1.8b大模型&#xff0c;占用显存2…

Centos怎么执行脚本

方法一&#xff1a;切换到shell脚本所在的目录&#xff08;此时&#xff0c;称为工作目录&#xff09;执行shell脚本 cd /data/shell ./hello.sh 方法二&#xff1a;以绝对路径的方式去执行bash shell脚本 /data/shell/hello.sh 方法三&#xff1a;直接使用bash 或sh 来执行…

Kubernetes深入详解(一)

目录 第一部分 K8s概念和架构 1、k8s概述和特性 2、K8s架构组件 3、k8s核心概念 第二部分 从零搭建k8s集群 1、搭建k8s环境平台规划 2、服务器硬件配置要求 3、搭建k8s集群部署方式 (1) 基于客户端工具kubeadm 1、安装Docker 2、添加阿里云YUM软件源 3、安 装kubea…

代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 图论part08**拓扑排序精讲**题目&#xff1a;117. 软件构建拓扑排序的背景解题思路&#xff1a;模拟过程 **dijkstra&#xff08;朴素版&#xff09;精讲**题目&#xff1a;47. 参加科学大会解题思…