代码之家  ›  专栏  ›  技术社区  ›  Dario

C风格句法的客观优势

  •  7
  • Dario  · 技术社区  · 16 年前

    有很多编程语言深受C样式语法(花括号、分号等)的影响,可能比其他任何语法样式的影响都大。直到今天,许多现代的、成功的或甚至新发明的语言都使用了这种语法——只考虑Java、C++、C语言、PHP、JavaScript、C、Perl等。

    有什么客观的原因可以解释这种语法的广泛传播和成功吗?与其他语言的语法相比有什么优势吗?

    10 回复  |  直到 8 年前
        1
  •  15
  •   Community CDub    8 年前

    imho,使C风格语法流行的唯一原因是大多数人都知道它。因此,对新语言使用C样式可以应用旧的habbits(如命名约定)。这是件好事!尽管我认为,语法是学习一门新语言最不关心的。但是一个好的语法可以帮助避免错误。

    微软做了很多努力使vb.net和c一样重要(记住所有的 无效的 ( 没有什么 在VisualBasic中),这让我很恼火,但C仍然是.NET平台的主要语言。vb.net似乎与它的前辈们的坏名声有关。不过,使用C样式看起来更专业。

    毕竟,C的设计目标之一是使编译器易于实现。使用预处理器比为常量定义新的语言构造更容易。或[5]的语义。这不适用于C++,这是非常难以实现的,部分原因是它试图与C保持兼容。

    实例:

    • 区分大小写,虽然不区分大小写对人类更为自然(而不是对计算机)。这并不意味着您应该以不同于声明的方式拼写标识符(当心!)但会导致混乱。真实世界示例(Java):GETWITESPACE()还是GETWEATSPACE()?

    编辑: 另一个很好的例子: What is the worst gotcha in C# or .NET? . 但是,当然,一旦你习惯了它,在一个IDE的帮助下,这不再是什么问题了,有时甚至更自然,因为它更像计算机的实际工作方式。

    • 运算符优先级

    • = 转让和 == 为了比较。 if (a = b) 有人吗?类似的 && & , || | , ! ~ )在句法上过于接近,尽管它们意味着不同的东西。我个人比较喜欢 and or 因为符号应该只支持语法而不是主要部分。

    • ++ -- 运算符;使某些语句略短一点,但会给表达式带来副作用( a = b+++b++ )最初,编译器可以比 i = i + 1 .

    • for(init;condition;step) 循环;尽管最佳实践是仅使用它来增加变量,但不存在用于此目的的显式语法。相反,这个for构造是多余的,因为它(几乎)与

      init;
      while (condition) {
        statement;
        step;
      }
      
    • switch 声明;忘记休息了吗?为什么不像大多数其他语言那样允许范围作为大小写标签呢?

    • if(condition) 语句。使用括号不是一个很好的选择,因为它可以用于条件表达式本身:

      if (!(var & 0x02))
      
    • 预处理器

    • 支撑。这是有争议的。我不同意这样的说法,即这些“不使用太多的屏幕属性”,是更简洁或更快的书写速度。首先,一种语言应该设计为易于阅读,而不是易于书写。其次,根据您的风格,大括号使用的屏幕空间量与关键字的使用量完全相同:您将它们写在一行中。那不是浪费了很多空间吗?

      此外,人们批评Lisp的括号杂乱无章。你从来没有想过你必须数你的牙套才能找出你错过的地方?我有时会在右大括号后添加一条注释,以指示此处应该结束的内容。基本语法已经包含了这个。甚至不需要一个等效的开口撑。 部分我同意大括号是好的:它们几乎看不见,缩进是主要的视觉特征。从这个角度看,python是下一步。

    • 分号作为语句终止符或分隔符。为什么单个分号是有效的语句?

      if (condition);
        DoSomething();
      
    • 不可区分的关键字序列

      public static string main()
      

      它是方法声明吗?还是变量声明?还是函数原型?或者别的什么?例如,一些标点符号(以及每个声明类型的关键字)可以在这里帮助清晰地分隔返回类型。这就是C++难以解析的原因。

    • 正交性。 {} while (condition) 不适用于语句后接块的其他语言构造。我想VB的

      do [while/until condition]
        Statements
      loop [while/until condition]
      

      一个很好的解决方案,因为您有4种不同语义的可能组合:do/loop关键字之后的until/while。

    • 变量类型修饰符的奇怪顺序。

      int * const & i [];
      
    • 类型和变量名只出现在彼此之后,没有标记表明它是局部变量声明。斯卡拉使用 瓦尔 var 必须指示一个最终/可变变量的声明,并且类型由冒号分隔。在大多数其他方面,Scala使用Java语法。

    • 赋值运算符返回值;语句(带效果)和表达式(只返回值)之间没有区别

    编辑: 这里还有一些例子: https://stackoverflow.com/questions/163026/what-is-your-least-favorite-syntax-gotcha

    你肯定不会同意这些观点中的许多,并且不是所有的都是否定的(例如分号),或者我知道一个对所有情况都更好的解决方案。即使我愿意,最终的语言也不会是完美的语言。编程语言将不断发展,新发明的语言有望从它的前辈那里学习。那么,为什么不保持已知的语法,而不是从每十年设计一个新的语法呢?

    然而,当一个语言设计者有可能避免仅仅是输入错误的编程错误时,为什么不改变它呢?例如,这是在C的switch语句中完成的,这使得break(或goto)成为强制的。一旦最坏的缺点被消除,大多数程序员了解其余语法语法的好处远远超过从头重新设计语言的好处。但是我仍然感到惊讶,为什么这么多程序员仍然如此热心地为C语法辩护,尽管这些已经习惯了计算机科学的进步,但几乎所有的东西都需要定期的修改。

    总而言之,我认为C语法占主导地位的唯一原因是几乎所有专业程序员都知道C语法,而这些人只是习惯了它。尽管其他语言可能有优势,但实际的语法并不那么重要。这也是电气工程师使用电荷法则的原因。

    https://imgs.xkcd.com/comics/urgent_mission.png

    (也许也会有一个关于一个访问丹尼斯·里奇的程序员的漫画:“拜托,不要 打破 S在 转换 语句可选!“)

        2
  •  4
  •   Electrons_Ahoy    16 年前

    正如我看到的,实际上只有三个主要的语法元素从C带到了世界其他地方:用大括号表示的块,用分号表示行的结尾,以及一般的“简洁”风格。

    用一个字符包装块是相当合理的;首先,它打字速度快,不会占用很多屏幕的实际空间(不像一对开始端关键字)。第二,语法相当灵活,因此在特殊情况下(在类似于python的情况下,您不可能真正做到这一点),您可以根据需要/想要来格式化块。最后,您的代码可以被类似于email客户机的东西大量占用,并且仍然可以被人和编译器读取(这是我对python sty唯一真正遇到的问题)。块的缩进)。

    为什么要用大括号?我不知道在C语言中使用它们(或者,更可能是BCPL)的历史先例是什么,但我可以大胆猜测。“标准”美国键盘上没有那么多成对的符号:[]()和<>。如果我们想让编译器上的生活更轻松,我们需要开始和结束的唯一符号,所以对块结束使用类似或的符号是不可能的。在我们的配对中,实际上是唯一一个没有意义的-(1)和(2)都有很多数学包袱(这些包袱或多或少是通过函数和数组直接翻译的),而这两者都是各种各样的东西。我也会选择作为街区。

    对于一种新的语言,如果不使用关键字或缩进,为什么要更改它?很多程序员习惯用它们来表示块,为什么要使所有的肌肉记忆失效呢?

    同样的论点也适用于使用分号。使用一些东西来表示行尾,这样编译器的生活就容易多了。只使用一个字符使程序员的生活更容易。通过扫描键盘上的单个字符,从数学上讲,分号是少数几个意义不大的字符之一。从英语语法的角度来看,句点(或者逗号)最有意义,但它们已经被用作小数点了。而且,如果你斜视一点,用分号作为你的行终止符有一个相当类似的意思在英语中。再说一遍,如果你要开始一门新语言,为什么要改变它?

    至于基本的简洁性,我认为这是你能客观地说的唯一一个好主意。我能输入的字符越少,在离英语足够近的情况下就能把这个想法传给计算机,效果越好。

    (你可以说,大多数C类型语言也借用了大部分关键字词汇表,但实际上,大多数C类型的关键字都来自于旧的语言,如algol、fortran和bcpl,实际上,它们都是(大部分)常识。同样,一旦您培训了编程社区,“while loop”是什么,为什么要更改名称?)

    我认为现在任何一种不使用C语言语法的语言都是这样做的,因为一些基本的范式转换(比如Python的缩进方法)。如果你正在创造一种基本上工作方式相同的语言,为什么要改变什么呢?你的目标观众已经可以用他们的小指敲击花括号键了,为什么要使这项特殊技能一文不值?

    或者,把最后一句话再向前一步,如果你想在你的新的、游戏改变的语言(Java、C等)上销售程序社区,如果你的客户都已经知道了语法,你将有很多障碍。

        3
  •  3
  •   Andrew Hare    16 年前

    我认为这只是风格问题,而不是优势问题。

        4
  •  1
  •   anon    16 年前

    块结构语言必须以某种方式指定块。帕斯卡语言家族的相对不受欢迎似乎表明关键字不是一个很好的方法。另一方面,python的流行可能意味着将来更多的语言将只使用缩进来表示结构——希望不是这样。

        5
  •  1
  •   ennuikiller    16 年前

    当C是一种简洁易懂的语言时,我们应该知道为什么要发明一种全新的语法。这也有助于大多数程序都熟悉C语言,而语言本身是在C语言中实现的。这就是为什么要尝试改进已经很好工作的东西的一个例子。

        6
  •  1
  •   Stack Overflow is garbage    16 年前

    人们习惯了。当它被发明的时候, 每一个 语言是丑陋的地狱。当时,C因吸奶量少而受到欢迎。(也许是因为比口齿不清更脚踏实地)。

    今天,其他语言重用语法是因为程序员对它很熟悉。

    我觉得没有什么比这更重要的了。我更喜欢大括号而不是begin/end(虽然大括号在许多非英语键盘上都很痛苦),但是仍然有很多C语法的奇怪之处可以做得更好。C++发现返回类型可能更适合 之后 参数(C++0x允许使用这种语法,因为它与其他新特性如DeCype一样更好)。

    大多数函数语言都意识到参数周围的括号通常是不必要的。就这一点而言,显式键入通常也不是必需的。但大多数语言都是从C继承的,因为“这就是语法”。首先键入,然后键入变量/函数名。

    我们甚至不要去讨论函数指针的可憎之处。当然,我们可以为 他们的 类型。或者尝试对数组类型进行typedef。

    还有一种奇怪的操作员选择。为什么不使用“and”而不是&&?

    C的语法不好。它完成了任务,我们已经习惯了,它可能会留在这里。但这不是“好的”。

        7
  •  0
  •   mouviciel    16 年前

    C样式的语法非常紧凑。根据情况,这是一个缺点或优势。无论如何,这对高级C编码人员来说是一个生产力的提升。

    许多新的语言正式要求C继承,例如C++,C语言,Objto-C。

    此外,我猜许多语言创建者都有一个很大的C背景。不管有意与否,他们都可以用自己的新语言复制自己最了解的内容和最有效率的判断。

        8
  •  0
  •   Pete Kirkham    16 年前

    有什么客观的原因可以解释这种语法的广泛传播和成功吗?

    不太客观,但C有三个主要的历史优势:

    • 它比当时的其他语言更简洁(使用而不是algol的begin/end)
    • 它没有明显的缺点(例如fortran有歧义,并且不支持一行上的多个语句)
    • 在它流行之后,几乎所有其他语言设计师都知道C,并且可能在C中工作来构建他们的语言工具集。

    与其他语言的语法相比有什么优势吗?

    具有显式块和语句分隔符允许多个语句表达式;例如,在Python中不能使用多语句lambda表达式(而不是在C中有lambdas,尽管您在最新的C++中使用)。只需为块键入一个字符是一个次要的优势,但不是很大的优势(设置一个编辑器来匹配“begin”到“end”可能比匹配C(“”或“?”更容易)。?<“)到(”或“??>“”,如果输入速度是编程中的限制因素,则可能不会自动执行应执行的任务)。

        9
  •  0
  •   corlettk    16 年前

    至于为什么要用大括号…原因有二:

    1. 风洞效应。只有这么多 好的 任何给定问题的解决方案,分析的越多,这些问题的解决方案就越相似。因此,2009年的雪佛兰更像2008年的福特,而不是57年的雪佛兰,57年的福特…新雪佛兰和新福特设计在同一个风洞。大括号和分号使工程变得简单,使C比类似的“块”样式的语言更容易解析(对计算机和人类而言)。因此,C语言非常类似于Java,所以我有时会暂时忘记我使用的是哪种语言。

    2. (如前所述)对于程序员来说,学习一种“看起来和感觉像”前一个模型的新语言要容易得多。不要重新发明轮子,它不会滚到你身上;-)

    干杯。基思。

    附言:我预测50年内我们将使用“自然语言”编译器…怀念冰壶花括号语言的美好时光,男人在那里,羊在那里害怕。

        10
  •  0
  •   Marco van de Voort    8 年前

    afaik C的流行与unix的流行直接相关,而与它的语法无关。这一点有多个方面:它的低级语言(*)和瘦 强制性的 库适合于内核开发,编译器的可用性,相对早期的跨系统兼容性尝试。

    如果我不得不说出第二个原因,它将是相对松散的构建模型(编译单元只在链接器上相遇,只有链接器第一次看到(主要是消化的程序)完成),这对于低内存系统来说是很好的。

    代码密度常被称为,但这是后来的修正主义。对于以后采用这种语法的语言,更希望它能使升级路径比语法的优越性更容易。除了blockSyntax和name之外,这在C中是明显可见的,它离C非常远。

    (*)我更多地暗示了许多编译器助手的缺失。如果将libgcc降低到k&r级别,则会或多或少地减少它的内容。