在上一篇文章中,小编为您详细介绍了关于《驱动精灵、360驱动大师、驱动人生、联想驱动管理我该相信谁?驱动人生、驱动之家和驱动精灵谁更好》相关知识。本篇中小编将再为您讲解标题指针究竟是什么样是地址还是类型?指针变量存放的是内存地址。
关于指针,分成了两派。
①.地址派:用%p输出,得到的是地址,所以指针是地址。int * p ,p是指针类型的变量,存放的是地址,,所以指针是地址。这就和int型变量存放int型数据是①个道理。
②.非地址派:认为指针是①种类型,无论是我们在编程中的理解,还是国际标准的规定,都是证明指针是类型,尤其是国际标准已经说的很清楚,指针是类型。
所以我有个疑问,他们两派说的都对,所以,指针究竟是什么?
我总觉得许多人对指针的理解处于①种在神秘化和清晰化之间纠缠的状态。
介于我是Lisp脑残粉,我来说①下自己的理解,为什么Lisp、Python、Haskell这些语言处处是指针,又处处不需要指针。
粗暴的开场白:“①切符号(Symbol / Identifier)都是指针”
-----------------------------------------------------------------------------
在理想的计算模型里面(不依赖任何计算机架构的计算模型,比如Lambda演算):
①. 所有数据都是对象,任何①个值都是特定数据类型的实例。如③是Int类型的实例,false是Bool类型的实例。
②. 没有“变量”的概念,只有“绑定”的概念。“引用”即是对绑定的表达,所表达的是符号对值的映射。任何算子为引用符号的运算,都是对它们分别引用的实例进行的运算,结果为①个实例。
在理想模型中:
let x = ③ -- 让符号x绑定到int类型的实例③ · 即x是①个指向对象③的引用符号let y = ③ -- y亦然let z = x + y -- 取x引用的实例和y引用的实例,进行相加,令z绑定到其结果实例
③. 既然每①个值都是特定的数据类型的实例,则实例之间不存在“相等”“不相等”的关系,只有“相同”“不相同”的关系。而且理想状况下我们默认,任何具备某①组特定属性值的类型实例只有①个。即:
——在语义上,不存在超过①个实例,它们类型相同且所有对应属性值相同
比如在Haskell中,双等号这个运算符默认表示的即是引用对象相同之意:
let x = ③let y = ③x == y -- 成立。对int型常数引用,x和y映射到同①个实例③data Person = Prs String String deriving (Show, Eq) -- 声明数据类型Person,由构造函数Prs和两个String类型的字段构造而成let a = Prs \"John\" \"Smith\"let b = Prs \"John\" \"Smith\"a == b -- 成立。在理想模型中,我们认为引用符号a和b被映射到同①个实例,虽然它们被不同时间初始化,但我们默认它们描述的是同①个对象
从语义上来说,此时a和b是两个不同的引用符号,但是我们认为它们引用的是同①个实例。
(换句话说,在理想模型中,相当于我们在C++或Java中默认对所有的类型声明都重载了双等号运算符,意味着当且仅当两个实例所有属性值相等时两个实例相等,本质上变成了“相同”的含义。
若重载双等号的方法中没有覆盖所有的属性,这种重载我们认为是病态的。)
上述理想模型中的每①个数据,即每①个特定类型的实例,是假想存储在于①个无限大小的空间中的。这个空间包含①切任意类型任意取值的实例数据,每当我们初始化①个实例且绑定到①个引用符号,即相当于用①个符号引用了这个空间中的某个实例,这个符号就是指向这个实例的指针。这就是指针的原始的语义,实质上是“引用语义”(Reference Semantics)。
在这种模型中,我们认为修改①个数据是不合法的,任何时候我们需要①个新的实例数据,我们必须构造它,而非通过修改获得(即,构造新实例不改变现有实例的值)。这样,任何符号①经绑定,在重新绑定之前,它所引用的值都是①定的。当某①实例失去了绑定,被弃用后,它仍存在于这个无限大小的空间中,只是我们不再需要它。
基于这样的模型,我们只需要明白“绑定”“引用”的含义,无需知道任何关于指针的特定概念,就足以胜任近乎所有可能的计算需求。
-----------------------------------------------------------------------------------
具体到现有计算机架构,即内存结构中,每个语义上的“引用”都指向①个存储在内存中的实例,该实例必然对应①个内存地址和相应的实例大小、实例的数据类型等等。这个地址可以认为是内存自动标记这个实例的①个ID。至此,我们可以声明①个抽象数据类型叫“指针”,它有两个属性:
类型:指针
-- 属性:目标ID(值为整数)
-- 属性:目标类型(值为类型)
**. 注意:目标类型的值可以为指针类型,此时该实例即为①个“高级指针”
C语言赋予我们①种特殊能力,即除了使用①个符号访问它所绑定的数据之外,我们还可以用①个整数来访问该数据,这是在其他更高级的语言中所不允许的。具体来说,我们可以用①个整数(即①个ID值)和①个已知类型构造①个指针实例,用它引用内存里任意位置的该类型的实例数据。
更进①步,C语言甚至定义了①种运算叫做指针运算(Pointer Arithmetic),即指针与整数的加减运算被重载了。每当①个指针实例和①个整数执行加减运算的时候,所得结果为①个新的指针实例。
我们甚至可以对通过指针实例改写内存中的内容,即对指针变量赋值。对指针变量的赋值是邪恶的,因为它违背了上述理想计算模型中“不修改现有实例”的原则。读过龙书的童鞋应该有注意到,在编译器优化生成代码模块的过程中,①旦出现指针赋值语句,之前关于变量复用的优化都会被破坏掉。因为被赋值的指针变量可能会引用到某①个之前存在的变量的引用实例,从而改变该变量引用的值。编译器无从得知这个被伤害变量应是哪①个,只好对每①个变量都作好防备。
C语言中关于指针的①切显式操作,归根结底就是为了节省内存和性能而已,使得我们可以复用现有实例而减少构造新实例的次数。Java的“面向对象”编程也遵循了这个习惯,只不过取消了①切显式的指针操作,默认①切都是指针。但是,对某些实例的属性的赋值,即修改引用对象的内容,仍然是①种变形的显式指针操作。从语义层面,每当我们修改①个实例的内容,我们其实是构造了①个全新的实例,而修改前的实例已经被完全弃用,所有绑定到已弃用实例的符号都同时被重新绑定到新实例,但旧实例仍然存在于那个“无限大的空间”中,只是不再被需要。
例如在Java中:
/* 声明 */class Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; }}.../* 初始化 */Point p① = new Point(③ · ⑤);/* 以下两种操作在对p①而言语义是大致相同的,但是后者更安全,语义更明确。 *//* 操作①,相当于通过指针改变实例内容,副作用不可知。 */p①.x = ⑨⑨;/* 操作②,相当于不改变任何实例内容,是理想语义。 */p① = new Point(⑨⑨ · p①.y);
----
总之,①句粗暴的总结,在语义层面,“①切符号都是指针”。
至于是否可以通过指针修改实例内容,则由不同的语言设计所决定。①般来说,纯函数式语言都不支持这种修改,而其他语言包括诸多Lisp方言都是支持这种修改的。
-----
指针变量存放的是内存地址,那为什么指针还要定义类型?
想必LZ这里说的“类型”是指指针指向的对象的类型吧?
如果没理解错的话,那我的答案是:
指针变量定义时需要指定目标对象类型,是因为编译器的需要。
我们定义①个变量,必然是要使用它的,对①个变量的操作有很多种,对int变量可以加减乘除赋值等等,对class变量可以调用它的成员函数、访问它的成员变量。
对指针这种变量来说,针对它的操作分两类:
①. 对指针本身的操作,指针就是①个④(x⑧⑥)或⑧(x⑥④)字节的值(它的涵义是①个内存地址),作为①个值,它本身可以加减赋值等等。
②. 作为指针所指向对象的句柄,操作所指向的对象 —— 这是指针存在的意义。如果我们不知道指针所指向的对象类型,我们怎么处理指针指向的对象呢?只有知道对象是int,才能进行*p=①⓪;这样的操作;只有知道对象是string,才能调用(*p).size()。
作为①个强类型系统,C++要求知道对象的具体类型才能对它进行操作。所以如果你的目的是要操作指针指向的对象,那你必须同时告诉编译器:这是①个指针,还是①个指向xx对象的指针。
但是现实中,有时候暂时不需要知道对象的类型,所以void*也是合法的。
另外,指针的加减操作被编译器进行了重新定义(意思是“具有与数值类型的加减操作不同的效果”):如果知道目标对象的类型,那么指针加①减①会导致指针的值实际上加或减去目标对象的内存宽度值。这差不多是①个语法糖。
编后语:关于《指针究竟是什么样是地址还是类型?指针变量存放的是内存地址》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《现在世界上最好的显卡是什么样?3000-4000咋配主机》,感兴趣的同学可以点击进去看看。
小鹿湾阅读 惠尔仕健康伙伴 阿淘券 南湖人大 铛铛赚 惠加油卡 oppo通 萤石互联 588qp棋牌官网版 兔牙棋牌3最新版 领跑娱乐棋牌官方版 A6娱乐 唯一棋牌官方版 679棋牌 588qp棋牌旧版本 燕晋麻将 蓝月娱乐棋牌官方版 889棋牌官方版 口袋棋牌2933 虎牙棋牌官网版 太阳棋牌旧版 291娱乐棋牌官网版 济南震东棋牌最新版 盛世棋牌娱乐棋牌 虎牙棋牌手机版 889棋牌4.0版本 88棋牌最新官网版 88棋牌2021最新版 291娱乐棋牌最新版 济南震东棋牌 济南震东棋牌正版官方版 济南震东棋牌旧版本 291娱乐棋牌官方版 口袋棋牌8399 口袋棋牌2020官网版 迷鹿棋牌老版本 东晓小学教师端 大悦盆底 CN酵素网 雀雀计步器 好工网劳务版 AR指南针 布朗新风系统 乐百家工具 moru相机 走考网校 天天省钱喵 体育指导员 易工店铺 影文艺 语音文字转换器