C++编程语言的基本准则

C++编程语言的基本准则

无论是在工作还是生活中,如果我们要做一件事,较为普遍的做法是首先确定一个大方向,然后再逐步细化。这种天然的思想更明显的体现在科学理论中,比如数学,数学的整个庞大的知识体系都是基于最基本的公理推出来的,脱离原有体系的理论要么是错的要么将带来新的公理。C++中有许多编程规则,而这些规则的本源就是C++的基本准则。这些各种各样的规则在制定时都要严格遵守基本准则。

基于准则的重要性或者说优先级,下面来依次介绍:

1. 最高准则:无二义性

什么是二义性

所谓二义性,是指如果文法G中的某个句子存在不只一棵语法树,则称该句子是二义性的。如果文法含有二义性的句子,则称该文法是二义性的。

二义性有哪些解决办法

标准技术体系解决在程序设计语言中遇到的典型二义性,有两个解决二义性的基本方法。其一是:设置一个规则,该规则可在每个二义性情况下指出哪一个分析树(或语法树)是正确的。这样的规则称作消除二义性规则(disambiguating rule)。这样的规则的用处在于:它无需修改文法(可能会很复杂)就可消除二义性;另一种方法是将文法改变成一个强制正确分析树的构造的格式,这样就可以解决二义性了。当然在这两种办法中,都必须确定在二义性情况下哪一个树是正确的。这就再一次涉及到语法制导翻译原则了。我们所需的分析(或语法)树应能够正确地反映将来应用到构造的意义,以便将其翻译成目标代码。显然C++选用了第一种方法。

关于C++中无二义性

凡事都要有个结果,或者说分个对错。在严密的逻辑体系中更是如此。C++作为与数学同属逻辑体系的分支,同样要强调无二义性。C++规则中景六成的无二义性相关规则恰如其分的说明了无二义性的逻辑重要性。许多没有表面作用的规则背后都是对无二义性的遵守。

我们常说:“规矩是死的,人是活的”,这句话同样适用于C++的活动,尽管它并不是活的。宪法和刑法中的条例虽然很多,但无需观察便可知道,自从1987年以来,社会生活中罪犯的犯罪样例空间绝对要大的多。同样,C++在手捧宪法的时候也是较为灵活的执行的,具体的对一种可能引发二义性的行为来说:
1.C++将这种行为定义为非法,如规定变量名不能以数字开头,不能是关键字等。
2.在大的框架规则下再制定一套小规则,用来消除二义性,比如运算符的优先级规则。

实际上,如果较为死板的遵守准则,C++语法和句法就难免被约束,在面对许多问题时要么束手无策要么需要绕很大一个弯子,这么“死板”的“人”怎么在竞争激烈的语言社会中“生存”呢?

说了这么多,只是想来说明为什么要这样做,先因后果,现在来看下基于这种考虑制定的规则:

具体规则

1.标题运算符的优先级和结合性

在这里插入图片描述

2.标识符不能以数字开头

C++的标识符在不与已有函数名(系统或者自定义)、关键字重复的情况下,可以由数字,字母(区分大小写)和下划线构成,如Wanvote123,但是注意,不能以数字开头。
这是为什么呢。
根据网上的资料和自己的理解——这是为了方便区分变量和常量,从而便于编译器编译。
不妨先思考一下如果允许数字开头命名标识符的情况,那么如2E3这样的字符既可以表示变量名,也可以表示常量:2*10^3, 同样地,0x7C7D(16进制数),015(8进制数),0x45Lu(16进制无符号长整型)均具有二义性。
况且,C++规定变量命名只能用这三种字符,但是并没有规定一个变量中三种字符的个数,C支持如“”(亲测有效),"__"(亲测有效),"aabb"这样的变量名,如果支持以数字开头而又不修改变量中每种字符的个数的规定,那么像“123”这样的字符也是合法的变量名,这样一来所有的数字常量都可能看做变量,这给编译器编译工作带来极大的负担——这还是先解决能够区分常量变量的前提下,如变量可以以数字开头,但是不能全是数字,不能和“0x7C7D”,"2E3"等等计数法格式相同,等等等等,即精心设计一套命名规则——既支持以数字开头,又与已有的常量表示法则互斥,显然,这样做花费的精力太大,并且对于程序员记忆负担也过重,与其这样,还不如干脆不支持以数字开头命名常量。(其实C的设计者们是不是先设计了常量的表示法,然后再在它的余集中选择相对的简单的变量命名法则呢?)
所以,综上,以数字开头的变量名与C支持的常量表示法有重合的部分,编译时会产生二义性;即使重新设计支持以数字开头的变量命名法则,用于区分变量名/常量名的开销也太大,得不偿失,故不支持以数字开头。

3.贪心规则

是指编译器会尽可能多地结合有效的符号,而不管这样的结合是否合法。贪心规则的运行方式决定了其在某种程度上大大加快了运行的效率,但是因为其限定条件,可能经常不适用,或者报错。

贪心法则是为了消除二义性而设立的一些法则,是词法分析阶段消除二义性的法则。
最简单的,如i+++j,这个代码,可以解释称 i++ +j,也可以解析成i+ ++j,大家认为是哪一种解释?

词法分析阶段,C++普遍使用了贪心法则。
贪心法则就是,读了一个字符之后,C++会再读一个,看第二个字符和第一个字符合在一起能不能有意义,有意义的话就合在一起。

如i+++j,首先读入i,然后读入+。i和+合不成一个有意义的符号,没法贪心,因此,i是一个单独符号。然后再读入一个+,两个+可以合成一个++,可以贪心,然后就通过贪心法则合成一个++。
再读入一个+,三个+没法合成有意义符号,因此,两个+号变成一个单词,
再读入j,+与j合不成一个有意义符号,因此,第三个+ 单独成一个单词。

在比如字符串“\128ABC”,它的字符串长度是多少?
“\123ABC”,它的长度又是多少?

贪心法则,\128ABC,这个\会尽可能多地结合字符,但8不能出现在八进制中,因此,只能是\12一个字符,因为\128没有意义,没法贪心。但\127是有意义的,可以贪心,因此,根据贪心法则,\127就是一个单独的符号了
下面展示一些 内联代码片

// 实例
#include<iostream>
int main()
{int i=1;
int j=2;
int k=i+++j;
int g=sizeof("\128ABC");
int f=sizeof("\127ABC");
std::cout<<k<<"\n"<<g<<"\n"<<f<<"\n";
return 0;
}

结果:
在这里插入图片描述

2.第二高准则:高效性

C++语言将高效性作为次高准则,是因为C++语言出现时,计算机性能普遍较低,因此计算机性能是一个重要的制约因素,是主要矛盾。

如果有两个行为A与B,均满足无二义性规则,且A比要高效,则C++会选择A作为标准语法。如数组 小标选择0而不是1来索引。

需要说明,并非所有语言,都有对高效性的绝对要求

高效性准则只对基础的C++语法规则有效,在STL库与模板中,已经不再是次高准则了

1.数组下标0索引

关于C++中用0作为索引的高效性具体体现在
1.因为 C 的数组和指针很大程度上是重合的,而且有指针算数这个概念,而同时代的其他语言都是基 1,数组和也是指针是完全独立的。(C 这种做法对于操作系统编程比较方便,不信你在 pascal 里面给我实现个变长数组。)在这个前提下,使用偏移量而非传统的角标就更合适了。

2.p[0] 等价于 *(p + 0),即 *p,都是为了统一

3C++借鉴自C,而C最初是一门可以直接逐行翻译成汇编的语言这样做的好处就是下标可以直接等价成MOV值到偏移寄存器里,而基址寄存器里面保存的是数组头的地址,结合这两个就可以寻址取值.

4.c/c++中数组运算其实是指针运算的语法糖,源码经过编译除理后是没有数组这玩意的,这是前提。像a[n]这样的变量,a为首地址:当n从0起始,(a+n)就可引用到a[n]当n从1起始,则(a+n-1)才能引用到a[n]综上前者省去一步减法运算,更好。

5.参看https://link.zhihu.com/?target=https%3A//www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html.

2.逻辑短路

下面展示一些 内联代码片

// 
include <stdio.h> 
  int main()
 {
 int a=5,b=6,c=7,d=8,m=2,n=2;
 (m=a>b)&&(n=c>d);
 printf("%d\t%d",m,n);
 }

结果:

在这里插入图片描述

输出的结果为0,2。因为a>b为0,m=0,整个“与”逻辑判断就为“假”,所以后面的“c>d”就被短路掉了,所以n还是等于原先的2
&&只要有一个为0,都为0.因此计算机不计算(n=c>d);

3.第三准则:合乎日常习惯

程序设计语言最终是给程序员使用的。一套不合乎日常习惯的规则,会给程序员的使用带来极大的不便性,因为日常习惯的惯性极大,会使程序员最终放弃该语言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值