C 语言中,「.」与「

您所在的位置:网站首页 c语言里和:是什么 C 语言中,「.」与「

C 语言中,「.」与「

#C 语言中,「.」与「| 来源: 网络整理| 查看: 265

这个在C语言的确是遗留问题,从语法层面上, *. 和 ->是等价的,或者说编译器优化后等价。

其实严格抠标准,也不是完全等价,详见 @Milo Yip 的回答。

我补充一点:在访问空指针和野指针时有差别——空指针会挂在*解引用,野指针会挂在.访问内存。

但从语义层面上,这两者的确是有区别的,原因也源于C语言早期的设计思路,虽然不是题主补充的那样。

假设我们有个结构体

typedef struct { int x; int y; } Point; Point pos; pos.x = 10; pos.y = 5; Point* pPos = &pos; (*pPos).x = 15; pPos->y = 20;

由于C语言早期是作为汇编的通用翻译存在的,而从汇编或者说从机器的角度,就只存在三个概念——指令、寄存器、内存。

其中,寄存器的输入又是来自内存,是和指令打包使用的,所以其实相当于指令+寄存器打包为“代码”的概念,内存为“数据”的概念。

而内存是连贯的二进制数据,并不存在实际的类型和结构,编程语言里的类型,只是对内存的抽象。

因此, pos.x 从机器角度,是类似下面这样的(为方便理解,我也把它转换成c写法)

*(int*)(ADDRESS(pos) + OFFSETOF(Point, x))

即【取变量p的地址,偏移四个字节,将新地址作为int类型使用】

在这样的语义下,我们操作指针变量pPos时,如果写作 pPos.x ,按照上面举的例子,这个内存映射就完全不对了,所以必须先增加一个 * 来解引用。

然后,为了统一语法形式,同时简化编写,所以增加了一个 . 操作符的间接版本,就是 ->

所以,如果从语义上解释,这两个操作符的含义是这样的:

. 直接成员访问操作符 -> 间接成员访问操作符

当然,随着编译器优化,现代编译器已经可以识别代码实际要做的事,而不是粗暴的做翻译了,所以完全可以把 . 和 -> 合并,统一用 . 表示。

但我不建议这么做,这样语义上存在一定的模糊,或者说语义范围的扩大,与C语言简洁清晰的设计逻辑有悖。

================

而到了C++中,早期为了兼容C,全盘继承了这些东西,但在C++特性丰富起来以后,反而亏得当时没有把两个操作符合并,在后续版本中,才能通过更加丰富灵活的语法,将这两者的语义间的差异作出进一步的诠释。

说人话就是,运算符重载

≈≈≈≈ 偏个题 ≈≈≈≈

运算符重载通过不修改语法来扩展语义的形式,使得C++在许多领域,依旧比绝大多数更新更高级的语言好用得多,从代码编写和编译运行两个角度同时体现了零开销抽象的设计哲学的美感。

比如向量乘法, a*b 相比 a.*b 或者 mul(a, b) ,语法上与基础类型乘法获得完美统一,语义上也统一。

≈≈≈≈ 偏题结束 ≈≈≈≈

在允许运算符重载的C++中,结合模板技术,出现了智能指针这个玩意。

std::shared_ptr pPos = std::make_shared();

这个时候,pPos. 和 pPos-> 可就是完全不同的概念了,这两者把两个运算符的语义差异体现的淋漓尽致:

pPos. 直接成员访问操作符,操作shared_ptr这个对象本身的成员和方法,比如.use_count()操作的就是shared_ptr对象本身pPos-> 间接成员访问操作符,操作指针指向的对象的成员,如通过->a才是访问Point对象的x。

hmmm,这里还可以说是语言缺陷,因为零开销抽象和兼容C等设计约束和历史原因,无法像其他高级语言那样把指针语义整合到语言内部,所以才不得不做了智能指针类,不得不弄出一堆成员方法来扩展指针语义。

那么我再举个例子吧,迭代器。

QMap map; auto it = map.begin(); it.value().x = 5; it->x = 10;

这里就是运算符重载如何体现两种成员访问操作符的语义了。

这里我用QMap而不是std::map来举例,因为std::map的迭代器一般实现为std::pair*指针,语义的挖掘和使用的灵活性上个人觉得不如Qt。

由于map的迭代器,必须能够同时访问key和value,所以它必须具有key和value两个成员。

于此同时,迭代器的表现又应该类似于value*指针,可以通过*直接获得value,或者通过->访问value内容。这样和vector等容器、常规数组的迭代器表现取得一致,便于配合std::begin()/std::end()设计基于迭代器的通用算法。

此时,如果把两种成员访问操作符合并,在这个场景下,语义就会出现混淆。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3