由上节介绍我们知道,通过指针可以修改内存上的数据,并进一步可以交换数据。这种操作实际上也是在对地址进行操作运算。具体怎么实现指针变量的元素呢?为什么能实现指针变量的运算呢?

因为指针变量保存的是地址,而地址本质上是一个整数,所以指针变量可以进行部分运算,例如加法、减法、比较等。

#include <stdio.h>
#include <iostream>
using namespace std;int main() {int    a = 8, *pa = &a, *paa = &a;double b = 70.3, *pb = &b;char   c = '#', *pc = &c;//最初的值----打印地址cout << "---打印最初的7个地址---" << endl;printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c);printf("pa=%#X, paa=%#X,pb=%#X, pc=%#X\n", pa, paa, pb, pc);//pa和paa地址一样,因为都是指向a。//------------打印数据cout << "---打印最初的7个数据---" << endl;cout << a <<" , "<< b << " , " << c << endl;cout << *pa << " , " << *paa << " , " << *pb << " , " << *pc << endl;//*pa和*paa数据一样,因为都是指向a。//加法运算----打印地址pa++; pb++; pc++;cout << "---打印加法后的7个地址---" << endl;printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c);printf("pa=%#X, paa=%#X,pb=%#X, pc=%#X\n", pa, paa, pb, pc);//------------打印数据cout << "---打印加法后的7个数据---" << endl;cout << a << " , " << b << " , " << c << endl;cout << *pa << " , " << *paa << " , " << *pb << " , " << *pc << endl;//减法运算---打印地址pa -= 2; pb -= 2; pc -= 2;cout << "---打印减法后的7个地址---" << endl;printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c);printf("pa=%#X, paa=%#X,pb=%#X, pc=%#X\n", pa, paa, pb, pc);//------------打印数据cout << "---打印减法后的7个数据---" << endl;cout << a << " , " << b << " , " << c << " , " << endl;cout << *pa << " , " << *paa << " , " << *pb << " , " << *pc << endl;//比较运算-----打印数据if (pa == paa){printf("%d\n", *paa);cout << *paa << endl;}else{printf("%d\n", *pa);cout <<"不相等"<< *pa << endl;}return 0;
}

结果展示:

pa执行++之后,因为pa指向的是int型所以地址加4,pa此时指向了新的地址,至于新地址里边是什么数据我们没有对他进行赋值,所以不能操作极其危险,此时系统里边存的是1,所以就给我们1,至于为什么是1,我们不知道。

有上述代码可以看出:指针变量除了可以参与加减运算,还可以参与比较运算。当对指针变量进行比较运算时,比较的是指针变量本身的值,也就是数据的地址。如果地址相等,那么两个指针就指向同一份数据,否则就指向不同的数据。

从运算结果可以看出:pa、pb、pc 每次加 1,它们的地址分别增加 4、8、1,正好是 int、double、char 类型的长度;减 2 时,地址分别减少 8、16、2,正好是 int、double、char 类型长度的 2 倍。
这很奇怪,指针变量加减运算的结果跟数据类型的长度有关,而不是简单地加 1 或减 1,这是为什么呢?

以 a 和 pa 为例,a 的类型为 int,占用 4 个字节,pa 是指向 a 的指针,如下图所示:

刚开始的时候,pa 指向 a 的开头,通过 *pa 读取数据时,从 pa 指向的位置向后移动 4 个字节,把这 4 个字节的内容作为要获取的数据,这 4 个字节也正好是变量 a 占用的内存。

如果pa++;使得地址加 1 的话,就会变成如下图所示的指向关系:

这个时候 pa 指向整数 a 的中间,*pa 使用的是红色虚线画出的 4 个字节,其中前 3 个是变量 a 的,后面 1 个是其它数据的,把它们“搅和”在一起显然没有实际的意义,取得的数据也会非常怪异。

如果pa++;使得地址加 4 的话,正好能够完全跳过整数 a,指向它后面的内存,如下图所示:

我们知道,数组中的所有元素在内存中是连续排列的,如果一个指针指向了数组中的某个元素,那么加 1 就表示指向下一个元素,减 1 就表示指向上一个元素,这样指针的加减运算就具有了现实的意义。

不过C语言并没有规定变量的存储方式,如果连续定义多个变量,它们有可能是挨着的,也有可能是分散的,这取决于变量的类型、编译器的实现以及具体的编译模式,所以对于指向普通变量的指针,我们往往不进行加减运算,虽然编译器并不会报错,但这样做没有意义,因为不知道它后面指向的是什么数据。PS:警告读者不要尝试通过指针获取下一个变量的地址(因为你定义的几个变量他们可能并不挨着,它们中间还参杂了别的辅助数据)。

如上面的例子,在比较 pa 和 paa 的值时,pa 已经指向了 a 的上一份数据,所以它们不相等。而 a 的上一份数据又不知道是什么,所以会导致 printf() 输出一个没有意义的数,这正好印证了上面的观点,不要对指向普通变量的指针进行加减运算。

参考:C语言中文网

C指针3:指针变量的运算相关推荐

  1. c语言指针赋值指针变量赋值吗,C语言_指针变量的赋值与运算,很详细

    指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...

  2. C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)

    1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...

  3. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  4. 10深入理解C指针之---指针运算和比较

    该系列文章源于<深入理解C指针>的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教. 指针运算有很多种,主要有指针的声明*.指针的解引*.指针指向(*).或->.指针 ...

  5. 【C基础】指针/指针运算/二级指针/函数指针

    指针定义: 指针是一种数据类型,使用它可以用来定义指针变量,指针变量中存储的其实是整数,这种整数代表了内存的编号. 指针的使用: 1.函数之间相独立,但有些时候需要共享变量.传参是值传递全局变量容易命 ...

  6. c语言位向量机伞_一文读懂C语言精华-指针变量和指向指针的指针

    1978年贝尔实验室正式发表C语言,受到众多IT从业者的热捧,即使41年过去了,C语言仍然牢牢占据最受欢迎编程语言前二的位置,许多人的程序开发之路也是从C语言开始的. 编程语言受欢迎排名 C语言简洁紧 ...

  7. C 温故知新 之 指针:函数指针变量、指针型函数

    猛一看还真有点糊糊:注意区别: 1.函数型指针:指函数返回值的类型.    指针型函数:返回值是一个指针(即地址)   2.int(*p)()和int *p() 是一样吗?为什么?  int (*p) ...

  8. 翁恺老师C语言学习笔记(十)指针_指针运算

    我们先看一段代码 #include <stdio.h>int main(void) {char ac[] = {0,1,2,3,4,5,6,7,8,9,};char *p = ac;pri ...

  9. 翁恺老师C语言学习笔记(十)指针_指针变量就是记录地址的变量

    指针变量就是记录地址的变量 scanf函数 · 如果能够将取得的变量的地址传递给一个函数,能否通过这个地址在那个函数内访问这个变量 · scanf("%d", &i) · ...

最新文章

  1. 1.5w字,30图带你彻底掌握 AQS!
  2. 管好统计信息,开启SQL优化之门
  3. poj 2349 求MST中第S大的权值
  4. 如何使用window.btoa base64对接口数组进行加密处理
  5. mysql 数据库 文件夹_mysql 数据库 文件夹
  6. 清新浪漫风情人节海报PSD分层模板!
  7. 如果一年只能两次旅游,你会选择什么季节去什么地方?
  8. apache camel 相关配置_Web基础配置篇(二): Maven配置及使用
  9. MongoDB干货系列1-定期巡检之Mtools
  10. BabeLua--Lua调试器
  11. 2021计算机考研408真题和答案(回忆版)
  12. ★【博弈论】【贝蒂定理】取棋子游戏
  13. 显卡a卡和n卡的区别
  14. 《实变函数简明教程》,第三章:可测函数,连续函数复合可测函数是可测函数
  15. Maven系列之使用阿里云仓库
  16. 李宏毅机器学习Day03之误差
  17. 先锋录音系统服务器,先锋音讯IP电话云录音系统——全球首创
  18. 偏振光相机3——偏振应用
  19. springboot毕设项目教师绩效工资管理l1v8p(java+VUE+Mybatis+Maven+Mysql)
  20. 【高数】用拉格朗日中值定理解决极限问题

热门文章

  1. TCP/UDP对比总结
  2. leetcode-160-相交链表(simple)
  3. 解决xcode ***is missing from working copy
  4. python基础(三元运算+深浅拷贝+函数参数)
  5. Sublime Text 3 常用插件以及安装方法(转)
  6. 经典贪心法:时间序列问题及其全局最优性证明
  7. strcpy +memcpy实现循环右移
  8. List和ObservableCollection的相互转化
  9. mysql索引空间太大_MySQL优化索引
  10. es日期format_elasticsearch存储日期格式字段