&&在c语言中表示什么

基本上,每一个C语言程序员都明白点运算符“.”和箭头运算符“->”可以用于访问结构体的成员,只不过箭头运算符“->”需要与结构体指针结合使用。事实上按照现在流行的C语言语法,通过结构体指针直接访问成员,也只能通过箭头运算符。

struct test *x;
x.member = 1; // 非法
x->member = 1; // 合法
&&在c语言中表示什么

C语言为何要有“->”运算符?

C语言为何要有“->”运算符?

抛开结构体不谈,C语言中的指针本身并无需要用到点运算符“.”的地方,因此结构体指针与点运算符“.”结合时,编译器把这种结合解释为访问结构体成员,按理说并不会产生歧义,C语言以语法简洁闻名,那为什么还要提供“多余”的“->”运算符呢?或者说,C语言中的箭头运算符“->”有什么历史渊源吗?

上述问题其实可以简化成两个子问题,一是为什么C语言要有“->”运算符,再就是为什么C语言中的“.”运算符不能与结构体指针结合访问成员。

C语言“->”运算符的历史

其实,在C语言的第一个版本(相关C参考手册(C Reference Manual,CRM)在1975年5月随第6版Unix一起发布)中,“->”运算符并不像今天一样与“.”运算符同义,而是另有一种特有的含义。

&&在c语言中表示什么

CRM 所描述的C语言在许多方面都与现代C语言有很大的不同

CRM 所描述的C语言在许多方面都与现代C语言有很大的不同,例如 CRM 的结构体成员实现了全局字节偏移的概念,没有类型限制,可以访问任意地址。也就是说,当时的C语言中,所有的结构体成员的名字都具有独立的全局含义,因此所有结构体的成员名都不能一样。

struct S {
 int a;
 int b;
};

上面这几行C语言代码定义了结构体 S,成员 a 代表 0 偏移,而成员 b 则代表 2 字节偏移(这里假设 int 变量占用 2 字节内存,也不考虑内存对齐)。

当时C语言做了这样的限制:所有结构体的所有成员,要么有唯一的名字,要么代表唯一的字节偏移量,例如:

struct X {
 int a;
 int x;
};

上述代码定义了结构体 X,它也包含成员 a,它的名字与结构体 S 中的成员 a 重复了,但是没有问题,因为它们都代表 0 偏移。下面这种定义就属于非法了:

struct Y {
 int b;
 int a;
};

因为结构体 Y 中的成员 a 与结构体 S 中的成员 a 重名,并且代表的字节偏移量也不相等。

&&在c语言中表示什么

早期箭头运算符“->”是用于确定偏移量的

在当时的C语言语法中,箭头运算符“->”就是用于确定偏移量的。既然每个结构体的成员代表的字节偏移量都是全局的,那么下面这样的语句也是合法的:

int i = 5;
i->b = 42;
100->a = 0;

上述几行C语言代码的意义很明确:i->b 表示以 5 为基准的 2 字节偏移处,因此 i->b=42; 的意思是将地址 7 处的 int 值设置为 42。同样的道理,100->a=0; 则表示将地址 100 处的 int 值设置为 0。

读者应注意,在当时版本的C语言中,箭头运算符“->”并不关心它的左表达式,因此哪怕 100->a 也是合法的。

&&在c语言中表示什么

箭头运算符“->”并不关心它的左表达式

这样利用结构体成员偏移量的做法对于“* ”和“.”运算符的组合是不可用的,例如

int i = 5;
(*i).b = 42;

*i 本身就是一个无效的表达式,“* ”是一个独立的运算符,因此对其操作数施加了更加严格的类型要求。当时 CRM 引入箭头运算符“->”就是用于解决这种限制带来的不便的。

后来,在 K&R 设计的C语言中,许多 CRM 中的功能被重新设计,“结构体成员作为全局偏移标识符”的设计被完全推翻,此后箭头运算符“->”的功能与“* ”和“.”运算符结合的功能完全相同。

为什么C语言不支持“.”运算符与结构体指针结合访问成员?

同样,在 CRM 描述的C语言中,“.”运算符的左操作数被要求必须是一个左值,这也是它与“->”运算符不同的原因,如上所述。请注意,CRM 不需要“.”运算符的左操作数是结构体类型的,它只要求左操作数是左值。

这里读者应该区分“左操作数”和“左值”。

&&在c语言中表示什么

应该区分“左操作数”和“左值”

这意味着在 CRM 版本的C语言中,程序员可以编写下面这样的代码:

struct S { int a, b; };
struct T { float x, y, z; };
struct T c;
c.b = 55;

读者应该注意到结构体 T 并没有成员 b,但是 c.b=55; 却仍然是合法的,这是因为编译器不关心变量 c 的类型,它只关心 c 是否一个左值:某种可写的内存块。因此 c.b=55; 的意义是将 55 写入名为 c 的连续内存块中字节偏移量 2 处的 int 值中。

因此,如果我们写了下面这样的C语言代码:

S *s;
...
s.b = 42;

编译器将认为这样是有效的,因为 s 也是一个左值。最终得到的C语言程序将尝试将 42 写到指针变量 s 本身(而不是它指向的结构体)所在连续内存字节偏移量 2 处。不用说,这样的结果必定会产生预料之外的结果,很可能带来内存溢出,但是编程语言本身并不关心这些事情。

&&在c语言中表示什么

编程语言本身并不关心这些事情

也就是说,在那个版本的C语言中,对“.”运算符重载(使其支持通过结构体指针访问成员)根本就行不通,因为“.”运算符与指针结合时,已经具备自己的含义了(与左值结合,访问指定偏移量的内存)。虽然以今天的眼光来看,这样的设计很古怪,但是当时的确就是这样设计的。

当然了,这样的奇怪设计并不是“.”运算符不能与结构体指针结合使用访问成员的充足理由,但是后来 K&R 在重新设计C语言时没有考虑重载“.”运算符,应该是需要兼容之前版本的C语言,毕竟历史遗留下来的C语言代码也是需要得到支持的。

最后

可能也有读者认为,即使是今天的C语言,似乎“->”运算符也不是必须的,因为“* ”和“.”运算符结合就能轻易的代替它:

struct S *p;
p->b = 3;
// 完全可以使用下面这样的语句替换
(*p).b = 3;

既然简洁是C语言的特点,就应该做到极致,何必提供“多余的”箭头运算符“->”呢?的确如此,就功能性而言,“->”完全可以不要,但是在C语言程序开发中,我们还需要考虑程序员的感受,请看下面这两种写法:

(*(*(*a).b).c).d
a->b->c->d

它们的功能是一致的,但是第二种写法无论是书写,还是阅读,都要简洁的多。

&&在c语言中表示什么

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

未经许可,禁止转载。

免责声明: 文章源于会员发布,不作为任何投资建议

如有侵权请联系我们删除,本文链接:https://www.sws100.com/baike/332942.html

(0)
鸟叔鸟叔
上一篇 2023年 4月 9日
下一篇 2023年 4月 9日

相关推荐

  • 歌曲《晚风》歌词(歌曲《晚风》歌词伍佰)

    口白:我想带你去看周杰伦的演唱会,因为周杰 伦是我的青春,我也希望你是我的青春 宝,你看晚霞好美,如同你一样,奥力给 耶~ 昂~ 唱:将近的晚风快吹干整条小巷, 燃尽的灯光无法再将我们点亮, 要明白有些事情不能总靠想象, 大不了今晚继续喝到明天早上, 看不到希望的人还在自言自语说着, 抱怨得不到温暖的人还在继续作着, 他对着电话那头说着自己过得很好, 挂断之…

    2023年 5月 11日
  • 春风是哪个国家的品牌(骑春风250sr丢人吗)

    1994年成立的Motorcycle网是北美地区最专业的的摩托车媒体之一,他们每年都会评选各个细分领域的年度最佳车型,2022年的评选还在逐个组别进行之中,率先公布的是轻量级/入门级车型组别的评选结果,获评年度最佳的是来自中国春风动力的700 CL-X,第二名是来自印度的皇家恩菲尔德Classic 350。 过去五年这个组别的年度车型得主分别是KTM的390…

    2023年 4月 12日
  • 荧光剂对婴儿的危害(荧光剂对婴儿的危害图片)

    再生纸所制造的作业本肉眼可见表面杂质较多 松树桥中学门口超市所卖普通作业本 权威部门对不同纸张可迁移性荧光剂检测报告 工作人员在智博会现场做荧光测试 智博会现场展示的环保作业本 可迁移性荧光剂测试(正常灯光下) 市面上普通的作业本(左)与环保作业本(右) 马上就要开学了,你给孩子准备的学习用品里面肯定有作业本吧,小心,可能你买的作业本里藏着一个大“秘密”! …

    2022年 10月 16日
  • 叮咛的咛组词100个(叮咛的咛组词什么)

    不久前的一篇《夜读》下,有位读者分享了这样一个比喻句,引得不少朋友点赞: 有位作家说:“精彩的比喻,仿佛是童话里的魔棒似的,它碰到哪里,哪里就忽然清晰明亮起来。” 今天,《夜读》又带着魔法般的比喻句来啦! 那些魔法般的比喻句 原来 一件事物还能这样描述 一种感受还能这样表达 01 形容【心上人】 她是会走路的月光。——佚名 02 形容【好心情】 她高兴得走路…

    2023年 4月 16日
  • 西藏日喀则海拔多少米(西藏日喀则海拔多少米火车z字头是快车吗)

    天地间,我牵挂的,只有那一眼, 第一缕圣洁的阳光撒向珠穆朗玛, 第一块轻盈的流云飘过多情措 , 我离天堂很近。 日月里,我守候的,只有那一刻, 璀璨的银河高悬于雪域圣地的夜空, 无际的格桑绽放在这世界屋脊之上 , 我离时间很近。 千年的爱恋,你是我心中的佛 , 千年的等待,思念流成了河, 在辗转轮回中,只愿为你漂泊。 我离你很近。 在这雪域的第三极, 在这神…

    2023年 3月 18日

联系我们

在线咨询: QQ交谈

邮件:k37759@foxmail.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信