大多数编程语言似乎设计为不允许人声明以数字开头的标识符。我只是好奇地知道原因。我已经在网上搜索过,但是找不到令人满意的解释。
大多数编程语言似乎设计为不允许人声明以数字开头的标识符。我只是好奇地知道原因。我已经在网上搜索过,但是找不到令人满意的解释。
Answers:
在C / C ++中,数字后跟字母被认为是数字常量,其后的字符串限定了常量的类型。例如(这些是VC ++,不确定它们的标准):
因此,a)对于Danieler来说,词法分析器比较容易,但b)由于0y 可能是变量,而0u 却不是,因此做出了明确的区分。再加上其他限定词,例如“ i64”,要比“ l”或“ u”晚添加,并且他们希望保持选择,如果需要的话可以添加更多。
实施词法分析器的人员的便利。(不,很重要,仅此而已。各种语言都有其他原因,但最终归结为这一点。)
0flu
是文字并且0glu
是本地标识符,那将是非常尴尬的。
int 0u = 5; unsigned int x = 0u;
但是,您选择定义此代码的解释(可能x == 0或x == 5),人们会感到困惑因为模棱两可。即使以这种方式实现编译器很简单,一个好的设计人员也可能不会这样做。
考虑以下两种情况:
假设标识符可以以数字开头。
因此,如下所示的语句将是有效的(因为标识符可以具有1个或多个字符):
int 3;
当我尝试在程序中使用以上变量时,将导致编译器模糊:
int 3,a;
3 = 5;
a = 3;
在语句a=3
中3的作用是什么(它是一个值为5的变量还是数字3)?
与上面的示例相反,让我们假设一种语言实际上是允许以数字开头的标识符,而仍然不允许使用数字作为标识符。这可能会导致以下问题:
有关变量的语言规则(该变量表示一个变量可以包含1个或多个字符)必须重新定义为复杂的规则,例如:变量可以具有一个或多个字符,并且如果不以数字开头则必须是唯一的。以数字(等)开头时,不能为单个字符长度。
当所有数字(例如333)和有效字母后缀(例如34L)用作变量名时,编译器将必须检查并报告错误情况。在像Python和JS这样的松散类型语言中,您可以在不声明变量的情况下即时使用变量,甚至可能无法检查涉及所有数字的特殊情况,例如,if (33==5)
此处33可能是用户声明的错误的未声明变量。但是编译器将无法识别此错误并报告错误。
进行此限制将防止程序员将数字用作标识符名称。
int char = float
会带来多大的灾难吗?
int
是关键字而不是标识符?嗯,int
就像数字词素一样,它具有更高的优先级。
int 3,a; 3=5; a=3;
在语句a = 3中,3是解释为标识符还是数字?这引起歧义。希望清楚。
在大多数情况下,这与简化编译器编写程序和简化分析效率无关,而与设计鼓励清晰易读的代码的语法有关。
语言设计人员认为,能够将数字1这样的数字文字写成纯1会很好。
这将是完全可能的设计,其中数字文字引述了以某种方式例如tildas所以对于一把手的数字小文字被编码为语言的语法〜1〜 ,任何事情不是关键字,而不是用引号括起来被视为一个变量名。
因此,您可以对如下语句进行编码:
1 = ~2~
two = 1 * ~2~
但是也:
2 = ~3~
six = 2 + 2
无论选择哪种语法,模棱两可且难以遵循的代码都是不可避免的。
C语言和C语言派生的大多数“花括号”语言也认为,允许程序员直接编写八进制和十六进制文字,并在重要的情况下指定文字的类型是一个好主意。所以
010 // Octal 10 = 8;
0x10 // Hexadecimal 10 = 16;
5l // long integer with decimal value 5
2.0d // double float with value 2
因此,即使您允许变量名以数字开头,然后是数字和字母的组合(包括至少一个字母),也会给程序员带来问题,即确定给定的组是形成变量名还是数字文字,这样
2lll = 22 // OK
2ll = 2 // compiler error
这样的歧义不会帮助任何人编写或阅读程序。
对于一个与现实世界密切相关的示例,您可以查看PL / 1语言,其设计者认为能够将关键字用作变量名是一个好主意,因此:
IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
IF IF THEN ELSE = IF; ELSE THEN = ELSE;
DO WHILE (WHILE = DO); END = WHILE + DO; END;
是可编译执行的有效代码。
Fortran对后来的语言设计产生了巨大影响。早期(其中一些问题已得到修复),Fortran 几乎没有规则来限制您可以给标识符赋予的名称。这使得该语言对于编译器和程序员都极难解析。这是一个经典的例子:
if if .eq. then then = else else else = endif endif
K I K K I I K I I K
在这里,我用K和标识符(变量名)I标记了“语言关键字”。鉴于拼写没有区别,我想您可能可以理解这会造成多大的混乱。当然,这是一个极端的例子,不可能有人故意写出像这样的代码。有时,人们还是将“语言”关键字“回收”为标识符名称,而且在很多情况下,简单的输入错误可能会导致代码被语言规范所说明的方式解析,即使这根本不是故意的。对于另一个众所周知的示例,请进行以下比较:
do 10 i = 1,10
对此:
do 10 i = 1.10
第一个是do循环-迭代一个代码块10次。但是第二种方法是将逗号更改为小数点,因此它将值分配给1.10
名为的变量do 10 i
。
这也意味着编写一个Fortran解析器相对困难-您无法确定do
该行的开头确实是一个关键字,直到您到达该行的末尾,并验证了a的所有其他元素do
循环存在。解析器通常必须做好“回溯”的准备,从一开始就重新解析行,以得到真正存在的“正确”(但通常是意外的)答案。
经过几年的努力,语言设计人员(无论如何还是大多数人)都走到了相反的极端-尽可能限制语言的几乎所有内容,而用户不会抱怨太多。
例如,早期的BASIC基本上说您甚至不能使用关键字作为标识符的一部分 -例如,fora=1
将其解析为for a = 1
(即,for
循环的开始,而不是赋值)。这显然引起了足够的抱怨,持续了很长时间。关于以数字开头的标识符的规则显然并没有引起很多抱怨,因此继续使用它(至少在大多数语言中)。
这不是编程语言在逻辑上必需的规则,而只是许多语言设计人员所使用的约定。
我可以设计完全不同的语言,以允许所有字符用作标识符。对于所有代码行,前20个字符将描述语句类型,然后下20个字符将定义该语句的第一个符号,后20个字符是该语句的操作数。该语言将在堆栈处理器上执行。
01234567890123456789 01234567890123456789 01234567890123456789
decl symbol 12345
assign value 12345 12345
decl symbol 99999
assign value 99999 12345
push 12345
push 99999
add
print top
该代码可以用C语言翻译如下:
int i12345 = 12345;
int i99999 = 12345;
printf("%d", i12345+i9999);
就这样。这是没有意义的,在逻辑上,标识符中的无编号规则也没有意义。