实际上,“ C样式语言”的定义可以简化为“使用花括号({})”。我们为什么要使用该特定字符(为什么不使用更合理的字符(如[],至少在美国键盘上不需要Shift键)?
这些花括号会给程序员的生产力带来实际的好处,还是新的语言设计师应该寻找替代品(例如,Python背后的人)?
Wikipedia告诉我们C 使用大括号,但不是为什么。Wikipedia上有关基于C的编程语言列表的一篇文章表明,此语法元素有些特殊:
广义上讲,C系列语言是使用类似C的块语法的语言(包括大括号来开始和结束块)。
实际上,“ C样式语言”的定义可以简化为“使用花括号({})”。我们为什么要使用该特定字符(为什么不使用更合理的字符(如[],至少在美国键盘上不需要Shift键)?
这些花括号会给程序员的生产力带来实际的好处,还是新的语言设计师应该寻找替代品(例如,Python背后的人)?
Wikipedia告诉我们C 使用大括号,但不是为什么。Wikipedia上有关基于C的编程语言列表的一篇文章表明,此语法元素有些特殊:
广义上讲,C系列语言是使用类似C的块语法的语言(包括大括号来开始和结束块)。
Answers:
对C的两个主要影响是Algol语言族(Algol 60和Algol 68)和BCPL(C以此命名)。
BCPL是第一种大括号编程语言,大括号在语法更改中幸免了下来,并成为表示程序源代码语句的常用方式。实际上,在当今有限的键盘上,源程序经常使用序列$(和$)代替符号{和}。BCPL的单行'//'注释在C中未使用,在C ++中以及随后在C99中重新出现。
来自http://www.princeton.edu/~achaney/tmve/wiki100k/docs/BCPL.html
BCPL引入并实施了一些创新,这些创新在后来的语言设计中已成为非常普遍的元素。因此,它是第一种花括号编程语言(使用{}作为块定界符),也是第一种使用//标记内联注释的语言。
来自http://progopedia.com/language/bcpl/
在BCPL中,人们经常看到花括号,但并非总是如此。这是当时键盘的局限性。在字符上,$(和和$)在字典上等同于{和}。 字母和字母组合在C中保持不变(尽管花括号替换使用- ??<和??>)。
花括号的使用在B(在C之前)中得到了进一步完善。
从Ken Thompson的用户参考到B:
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10, This routine uses the fact that
in the ASCII character set, the digits 0 to 9 have sequential
code values. */
printn(n,b) {
extern putchar;
auto a;
if(a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
}
有迹象表明,大括号被用作短手适应症begin和end内陵。
我记得您也将它们包含在您在CACM中发布的256个字符的卡代码中,因为我发现您提出可以代替Algol的“ begin”和“ end”关键字来使用它们很有趣,这恰好是后来如何在C语言中使用它们。
来自http://www.bobbemer.com/BRACES.HTM
方括号(作为问题中的建议替代品)的使用甚至可以追溯到更早。如前所述,Algol家族影响了C。在Algol 60和68中(C于1972年编写,BCPL于1966年编写),方括号用于将索引指定为数组或矩阵。
BEGIN
FILE F(KIND=REMOTE);
EBCDIC ARRAY E[0:11];
REPLACE E BY "HELLO WORLD!";
WRITE(F, *, E);
END.
由于程序员已经熟悉Algol和BCPL中的数组的方括号,以及BCPL中的块的花括号,因此在制作另一种语言时几乎不需要更改。
更新后的问题包括使用花括号的生产率附录,并提到了python。尽管答案可以归结为“它的轶事,而您习惯的是最有生产力的东西”,但是还有其他一些资源可以进行这项研究。由于编程技能和对不同语言的熟悉程度差异很大,因此很难解释这些问题。
另请参阅:堆栈溢出是否有统计研究表明Python效率更高?
许多收益将取决于所使用的IDE(或缺少)。在基于vi的编辑器中,将光标放在一个匹配的打开/关闭上,%然后按将光标移动到另一个匹配的字符。过去使用基于C的语言时,这非常有效-如今已不再如此。
更好的比较是/ {}和这是今天的选择(水平空间非常宝贵)。许多Wirth语言都基于和风格(Algol(如上所述),pascal(很多人熟悉)和Modula家族)。beginendbeginend
我很难找到任何可以隔离这种特定语言功能的东西-最多我能做的就是证明花括号语言比开始结束语言更受欢迎,这是一种常见的构造。如上面的Bob Bemer链接中所述,花括号用于简化速记程序的编写。
与{和}相比,C和Ratfor程序员发现“开始”和“结束”庞大。
可以说的全部-它的熟悉性和偏好。
{和}为??<和的三元组(在1989 ISO C标准中引入)??>。有向图(由1995年修订版引入)为<%和%>。在很早的翻译阶段,三部曲在所有情况下都得到了扩展。图是标记,不会在字符串文字,字符常量或注释中扩展。
x:=(c|s1|s2)代替C的x=c?s1|s2。同样,这适用于if&case语句。¢顺便说一句:A68是从外壳获得esac和fi的地方 ¢
[]自从IBM 2741终端(在Multics上广泛使用)操作系统以来,方括号的键入更加容易,而OS 2 终端则由 C语言创建者之一Dennis Ritchie 担任开发团队成员。

请注意,IBM 2741布局中没有花括号!
在C语言中,“大括号”被“采用”,因为它们用于数组和指针。如果语言设计师期望数组和指针比代码块更重要/更频繁地使用(这听起来像是一个合理的假设,更多地是在下面的编码样式的历史背景下),则这意味着花括号将变得“不太重要”。 “ 句法。
数组的重要性在Ritchie 的文章《 C语言的发展》中很明显。甚至有一个明确声明的假设:“ C程序中的指针盛行”。
...新语言保留了对数组语义的连贯且可行的解释(如果不寻常的话)... C语言在其同类语言中最有两个特征:数组与指针之间的关系... C的另一个特征C,对数组的处理…… 具有真正的优点。尽管指针和数组之间的关系不寻常,但可以了解。此外,该语言还具有描述重要概念的强大能力,例如,向量的长度在运行时会有所变化,只有一些基本规则和约定...
为了进一步了解创建C语言时的历史背景和编码风格,需要考虑到“ C的起源与Unix的开发紧密相关”,尤其是将OS移植到PDP- 11 “导致开发C的早期版本”(引文来源)。根据Wikipedia的说法,“在1972年,Unix用C编程语言重写了”。
各种旧版本的Unix的源代码都可以在线获得,例如在Unix Tree网站上。在这里介绍的各种版本中,最相关的似乎是1972-06年的第二版Unix:
肯恩·汤普森,丹尼斯·里奇和其他人在贝尔实验室为PDP-11开发了Unix的第二版。它通过更多的系统调用和更多的命令扩展了第一版。该版本还看到了C语言的开始,该语言用于编写一些命令...
您可以从第二版Unix(V2)页面浏览和研究C源代码, 以了解当时的典型编码风格。
在V2 / c / ncc.c源代码中可以找到一个著名的示例,该示例支持当时程序员很容易键入方括号的想法,这一点很重要:
/* C command */
main(argc, argv)
char argv[][]; {
extern callsys, printf, unlink, link, nodup;
extern getsuf, setsuf, copy;
extern tsp;
extern tmp0, tmp1, tmp2, tmp3;
char tmp0[], tmp1[], tmp2[], tmp3[];
char glotch[100][], clist[50][], llist[50][], ts[500];
char tsp[], av[50][], t[];
auto nc, nl, cflag, i, j, c;
tmp0 = tmp1 = tmp2 = tmp3 = "//";
tsp = ts;
i = nc = nl = cflag = 0;
while(++i < argc) {
if(*argv[i] == '-' & argv[i][1]=='c')
cflag++;
else {
t = copy(argv[i]);
if((c=getsuf(t))=='c') {
clist[nc++] = t;
llist[nl++] = setsuf(copy(t));
} else {
if (nodup(llist, t))
llist[nl++] = t;
}
}
}
if(nc==0)
goto nocom;
tmp0 = copy("/tmp/ctm0a");
while((c=open(tmp0, 0))>=0) {
close(c);
tmp0[9]++;
}
while((creat(tmp0, 012))<0)
tmp0[9]++;
intr(delfil);
(tmp1 = copy(tmp0))[8] = '1';
(tmp2 = copy(tmp0))[8] = '2';
(tmp3 = copy(tmp0))[8] = '3';
i = 0;
while(i<nc) {
if (nc>1)
printf("%s:\n", clist[i]);
av[0] = "c0";
av[1] = clist[i];
av[2] = tmp1;
av[3] = tmp2;
av[4] = 0;
if (callsys("/usr/lib/c0", av)) {
cflag++;
goto loop;
}
av[0] = "c1";
av[1] = tmp1;
av[2] = tmp2;
av[3] = tmp3;
av[4] = 0;
if(callsys("/usr/lib/c1", av)) {
cflag++;
goto loop;
}
av[0] = "as";
av[1] = "-";
av[2] = tmp3;
av[3] = 0;
callsys("/bin/as", av);
t = setsuf(clist[i]);
unlink(t);
if(link("a.out", t) | unlink("a.out")) {
printf("move failed: %s\n", t);
cflag++;
}
loop:;
i++;
}
nocom:
if (cflag==0 & nl!=0) {
i = 0;
av[0] = "ld";
av[1] = "/usr/lib/crt0.o";
j = 2;
while(i<nl)
av[j++] = llist[i++];
av[j++] = "-lc";
av[j++] = "-l";
av[j++] = 0;
callsys("/bin/ld", av);
}
delfil:
dexit();
}
dexit()
{
extern tmp0, tmp1, tmp2, tmp3;
unlink(tmp1);
unlink(tmp2);
unlink(tmp3);
unlink(tmp0);
exit();
}
getsuf(s)
char s[];
{
extern exit, printf;
auto c;
char t, os[];
c = 0;
os = s;
while(t = *s++)
if (t=='/')
c = 0;
else
c++;
s =- 3;
if (c<=8 & c>2 & *s++=='.' & *s=='c')
return('c');
return(0);
}
setsuf(s)
char s[];
{
char os[];
os = s;
while(*s++);
s[-2] = 'o';
return(os);
}
callsys(f, v)
char f[], v[][]; {
extern fork, execv, wait, printf;
auto t, status;
if ((t=fork())==0) {
execv(f, v);
printf("Can't find %s\n", f);
exit(1);
} else
if (t == -1) {
printf("Try again\n");
return(1);
}
while(t!=wait(&status));
if ((t=(status&0377)) != 0) {
if (t!=9) /* interrupt */
printf("Fatal error in %s\n", f);
dexit();
}
return((status>>8) & 0377);
}
copy(s)
char s[]; {
extern tsp;
char tsp[], otsp[];
otsp = tsp;
while(*tsp++ = *s++);
return(otsp);
}
nodup(l, s)
char l[][], s[]; {
char t[], os[], c;
os = s;
while(t = *l++) {
s = os;
while(c = *s++)
if (c != *t++) goto ll;
if (*t++ == '\0') return (0);
ll:;
}
return(1);
}
tsp;
tmp0;
tmp1;
tmp2;
tmp3;
有意思的是,有趣的是,根据在有针对性的实际应用中的使用情况,挑选字符来表示语言语法元素的务实动机如何类似于齐普夫定律,正如在这个绝妙的答案中所解释的 ...
观察到的频率和长度之间的关系称为齐普夫定律
...唯一的区别是上述语句中的长度被/概括为打字速度。
C(以及后来的C ++和C#)继承了其前身B的支撑风格,该风格由Ken Thompson(由Dennis Ritchie贡献)在1969年编写。
此示例摘自Ken Thompson的《用户对B的引用》(通过Wikipedia):
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10, This routine uses the fact that
in the ASCII character set, the digits 0 to 9 have sequential
code values. */
printn(n,b) {
extern putchar;
auto a;
if(a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
}
B本身又基于BCPL,这是Martin Richards在1966年为Multics操作系统编写的一种语言。B的支撑系统仅使用圆括号,并由其他字符修改(Martin Richards的打印阶乘示例,通过Wikipedia):
GET "LIBHDR"
LET START() = VALOF $(
FOR I = 1 TO 5 DO
WRITEF("%N! = %I4*N", I, FACT(I))
RESULTIS 0
)$
AND FACT(N) = N = 0 -> 1, N * FACT(N - 1)
B和后续语言“ {...}”中使用的花括号是Ken Thompson对BCPL“ $(...)$”中原始复合花括号样式的改进。