【C/C++知识点】指针的算术运算

简介: 【C/C++知识点】指针的算术运算

指针的算术运算

自增操作

下面代码中,p++ 的概念是在 p 当前地址的基础上,自增p对应类型的大小,也就是说 p = p+1*(sizeof(类型)) 。

#include<bits/stdc++.h>
using namespace std;
int main()
{
  int ages[] = { 21,15,18,14,23,28,10 };
  int len = sizeof(ages) / sizeof(ages[0]);
  int* p = ages;
  for (int i = 0; i < len; i++) {
    printf("数组的第%d个元素:%d,地址:0x%p\n", i + 1, *p, p);
    p++;
  }
  printf("------------------------\n");
  char ch[4] = { 'a','b','c','d' };
  char* cp = ch;
  for (int i = 0; i < 4; i++) {
    printf("数组的第%d个元素:%c,地址:0x%p\n", i + 1, *cp, cp);
    cp++;
  }
  return 0;
}


d23d049929b643a2966e204d4a351d6a.png


自减操作

操作与自增操作类似,只是从最后一个元素往前遍历。

#include<bits/stdc++.h>
using namespace std;
int main()
{
  int ages[] = { 21,15,18,14,23,28,10 };
  int len = sizeof(ages) / sizeof(ages[0]);
  int* p = &ages[len - 1];
  for (int i = len; i >= 1; i--) {
    printf("数组的第%d个元素:%d,地址:0x%p\n", i, *p, p);
    p--;
  }
  return 0;
}

b4229b35ae7548a9a05e32125c08a865.png

指针与整数之间的加减运算



指针与整数的运算,指针加减数字表示的意义是指针在数组中位置的移动。


对于整数部分而言,它代表的是一个元素,对于不同的数据类型,其数组的元素占用的字节是不一样的。比如指针 +1 ,并不是在指针地址的基础之上加 1 个地址,而是在这个指针地址的基础上加 1 个元素占用的字节数:


如果指针的类型是 char* ,那么这个时候 1 代表 1 个字节地址

如果指针的类型是 int* ,那么这个时候 1 代表 4 个字节地址

如果指针的类型是 float* ,那么这个时候 1 代表 4 个字节地址

如果指针的类型是 double* ,那么这个时候 1 代表 8 个字节地址

通用公式:


数据类型 *p:


p+n 实际指向的地址:p基地址 + n*sizeof(数据类型)


p-n 实际指向的地址:p基地址 - n*sizeof(数据类型)


比如:


对于 int 类型,比如 p 指向 0x0061FF14 ,则:

p+1 实际指向的是 0x0061FF18 ,与 p 指向的内存地址相差 4 个字节

p+2 实际指向的是0x0061FF1C ,与 p 指向的内存地址相差 8 个字节

对于 char 类型,比如 p 指向 0x0061FF28 ,则:

p+1 实际指向的是 0x0061FF29 ,与 p 指向的内存地址相差 1 个字节

p+2 实际指向的是 0x0061FF2A ,与 p 指向的内存地址相差 2 个字节

#include<bits/stdc++.h>
using namespace std;
int main()
{
  int ages[] = { 21,15,18,14,23,28,10 };
  int len = sizeof(ages) / sizeof(ages[0]);
  int* p = ages;
  printf("第7个人的年龄:%d\n", *(p + 6));
  printf("*p+6=:%d\n", *p + 6);
  printf("第3个人的年龄:%d\n", *(p + 2));
  int* p1 = &ages[4];
  printf("相对于第5个人,他前一位的年龄:%d\n", *(p1 - 1));
  printf("相对于第5个人,他前三位的年龄:%d\n", *(p1 - 3));
  return 0;
}


df595cf3d1264d08886005025941eac8.png


指针与指针之间的加减运算

指针和指针可以做减法操作,但不适合做加法运算

指针和指针做减法适用的场合:两个指针都指向同一个数组,相减结果为两个指针之间的元素数目,而不是两个指针之间相差的字节数。

如果两个指针不是指向同一个数组,它们相减就没有意义。

不同类型的指针不允许相减,比如 char* 和 int* 的指针相减,是没有意义的。

#include<bits/stdc++.h>
using namespace std;
int main()
{
  int ages[] = { 21,15,18,14,23,28,10 };
  int ages1[] = { 18,19,20,22 };
  int len = sizeof(ages) / sizeof(ages[0]);
  int* p1 = ages + 6;
  int* p2 = ages + 9;
  printf("p2-p1=%d\n", p2 - p1);
  printf("p1-p2=%d\n", p1 - p2);
  p1 = ages + 6;
  p2 = ages1 + 3;
  printf("p1:%p,p2:%p,p2-p1:%d\n", p1, p2, p2 - p1);
  return 0;
}

5811422e41a04ee089c1af7f572903f2.png

目录
相关文章
|
13天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
128 75
|
13天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
35 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
13天前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
37 12
|
13天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
35 9
|
13天前
|
存储 算法 测试技术
【C++数据结构——线性表】求集合的并、交和差运算(头歌实践教学平台习题)【合集】
本任务要求编写程序求两个集合的并集、交集和差集。主要内容包括: 1. **单链表表示集合**:使用单链表存储集合元素,确保元素唯一且无序。 2. **求并集**:遍历两个集合,将所有不同元素加入新链表。 3. **求交集**:遍历集合A,检查元素是否在集合B中存在,若存在则加入结果链表。 4. **求差集**:遍历集合A,检查元素是否不在集合B中,若满足条件则加入结果链表。 通过C++代码实现上述操作,并提供测试用例验证结果。测试输入为两个集合的元素,输出为有序集合A、B,以及它们的并集、交集和差集。 示例测试输入: ``` a c e f a b d e h i ``` 预期输出:
37 7
|
13天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
30 5
|
13天前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
27 5
|
1月前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
85 0
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
201 4
|
3月前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。