缩进风格

程式设计中,缩进风格indent style)是管理代码块缩进以表达程序结构的一种约定。本条目主要讨论自由形式语言,例如C及其后裔,但这也可以(并经常)适用于大多数其他编程语言(尤其是花括号编程语言英语Curly bracket programming language),其中的空白字符则并不重要。缩进风格是代码风格的一个方面。

缩进在大多数编程语言中不是必要条件,而只是作为辅助符号英语Secondary notation。不过,缩进有助于更好地向人类阅读者表达程序的结构。尤其是用于澄清控制流程结构(例如条件或循环)与其内部、外部代码之间的关系。不过,部分语言(例如Pythonoccam)使用缩进而非花括号或关键词来确定结构,这被称为越位规则。在这种语言中,缩进对编译器或解释器有意义,而不仅仅是清晰度或风格问题。

花括号位置

缩进风格的主要区别在于复合语句的花括号({...})的位置,这通常是为涵盖一个控制声明(ifwhilefor...)。下表展示了本条目中讨论的所有风格的所在位置。为了一致性,缩进深度(字符数)统一使用4个空格表示,这未考虑各风格中首选的缩进深度。

花括号位置 风格
while (x == y) {
    something();
    somethingelse();
}
K&R及变种:

1TBSStroustrupLinux内核BSD KNF

while (x == y)
{
    something();
    somethingelse();
}
Allman
while (x == y)
  {
    something();
    somethingelse();
  }
GNU
while (x == y)
    {
    something();
    somethingelse();
    }
Whitesmiths
while (x == y)
{   something();
    somethingelse();
}
Horstmann
while (x == y)
{   something();
    somethingelse(); }
Pico
while (x == y) {
    something();
    somethingelse();
    }
Ratliff
while (x == y) {
    something();
    somethingelse(); }
Lisp

制表符、空格及缩进尺寸

缩进的尺寸通常与风格无关。许多早期程序使用制表符来缩进,从而简化输入和节约原始码文件的大小。Unix编辑器通常将制表符视为等同八个字符,而MacintoshWindows环境将它视作四个字符[来源请求],这使代码在各环境间交换时产生一种混乱。现代的编程编辑器通常可以设置任意的缩进尺寸,并会插入适当的制表符与空格。对Ruby、许多shell脚本语言和某些形式的HTML格式,通常为每个缩进级别使用两个空格。[1]

使用制表符还是空格作为缩进字符是编程界的一项持续争论。杰米·加文斯基等一些程序员认为空格而非制表符有助增加跨平台可移植性[2]而如WordPress编码规范的作者则认为制表符增加了可移植性。[3]

工具

目前已有许多电脑程序可以自动校正缩进风格(依照程序作者或用户的偏好)以及制表符表示的缩进长度。其中很著名的一个是indent,这个程序包含在许多类Unix操作系统中。

Emacs中,有多种命令可用于自动解决缩进问题。

Elastic tabstops是一种需要文本编辑器支持的制表风格,当块中的一行的长度改变时,整个文本块将自动对齐。

风格

K&R

K&R风格常在C、C++以及其他花括号编程语言英语Curly brace programming language中使用。在布莱恩·柯林汉丹尼斯·里奇的《C程式设计语言》一书中也有使用。它起源于Kernighan和Plauger的《编程风格的元素英语The Elements of Programming Style》及软件工具。


变种:1TBS (OTBS)

变种:Java

变种:Stroustrup

变种:Linux内核

变种:BSD KNF

阿尔曼风格

变种:Allman-8

Whitesmiths style

GNU风格

Horstmann风格

Pico风格

Ratliff风格

Lisp风格

Haskell风格

Haskell是一种花括号可选的语言[4],也就是说,下面的两组代码在语义上是相等的:

braceless = do
  text <- getContents
  let
    firstWord = head $ words text
    bigWord = map toUpper firstWord
  putStrLn bigWord
braceful = do
  { text <- getContents
  ; let
      { firstWord = head $ words text
      ; bigWord = map toUpper firstWord
      }
  ; putStrLn bigWord
  }

通常,procedural do的段落和一般程序文本会省略花括号和分号,但这种风格通常用于由一对括号或花括号组成的列表、记录或其他句法元素,并用逗号或分号分隔。[5]

其他考虑

丢失块踪迹

在某些情况下存在着丢失块边界的轨迹的风险。这通常在包含许多复杂语句的大量代码中看到,这些复合语句嵌套了许多层的缩进。当程序员滚动到一大堆嵌套语句的底部时,他可能已经忘记了哪些控制语句转到哪里。不过,过长的代码也可能有其他原因, 诸如过于复杂,面对这个问题的程序员可能会考虑代码重构以期待它在未来有更好的体验。

for (int i = 0; i < total; i++) {
    foo(bar);
} //for (i)
if (x < 0) {
   bar(foo);
} //if (x < 0)

声明的插入

在使用标准的Unix行编辑器ed时,K&R风格能防止一个常见的错误。在控制语句与循环块的开启花括号之间错误地插入的语句将使循环体变为单次执行。

for (int i = 0; i < 10; i++)
    whoops(bar);   /* repeated 10 times, with i from 0 to 9 */
{
    only_once();   /* Programmer intended this to be done 10 times */
} //for (i) <-- This comment is no longer valid, and is very misleading!

K&R风格通过将控制语句和开启括号保持在同一行来避免此问题。

参见

参考资料

  1. ^ Detecting Code Indentation. 2014-09-08 [2017-07-28]. (原始内容存档于2020-11-12). 
  2. ^ Zawinski, Jamie. Tabs versus Spaces: An Eternal Holy War. 2000 [2016-06-06]. (原始内容存档于2018-06-12). 
  3. ^ WordPress Coding Standards. [2016-06-06]. (原始内容存档于2021-03-24). 
  4. ^ The Haskell 98 Report. [2016-03-03]. (原始内容存档于2021-04-11). 
  5. ^ Lipovača, Miran. Making Our Own Types and Typeclasses. [2016-02-03]. (原始内容存档于2021-04-13). 

外部链接