将函数类型和方法名称放在C中不同行的原因


16

我刚开始在一家公司工作,在我的第一次代码审阅中,样式注释之一是返回类型和方法名称应该在不同的行上。例如这个

void foo() {
}

应该是这个

void
foo() {
}

我一直使用第一样式,我想知道除了个人喜好之外,还有其他原因为什么人们使用第二样式吗?我认为第一个完全不会影响可读性。在C程序员和大型开源项目中,一种比另一种更普遍吗?


3
这是GNU标准中的(不一定表示这是一件好事,支撑样式很奇怪)。gnu.org/prep/standards/standards.html#Formatting
Gauthier

Answers:


19

想知道除了个人喜好之外,还有其他原因导致人们使用第二种风格吗?

这种风格在C的早期就很流行,所以原因可能就是他们很长时间以来一直这样做,他们有很多看起来像这样的代码,这就是原因每个人都习惯了。与其说个人喜好,不如说是公司发展的动力。

另一个原因是函数名称总是始于第一列。返回类型的长度各不相同,并且可能有些复杂-将类型放在自己的行上会使函数名称更易于查找。

如果公司采用固定样式,则他们可能还具有编码标准文档。去问问。它可能会解释选择此选项的原因,并且拥有副本将帮助您避免以后的评论中出现类似问题。


2
我想它也与许多程序员仍在使用和捍卫的80个字符行限制有关。如果要限制为80个字符,并且要使用描述性的方法/函数名称,则必须做出一些妥协。拆分方法标题是其中之一。
Sulthan 2013年

声明也可以更长-考虑不同的(非标准)修饰符,例如调用约定标识符(stdcall等),符号可见性信息(DLLEXPORT)或__attributes。然后,在研究C ++时,您可能具有相对复杂的返回类型,因此可能必须在其中添加换行符。
johannes

@Sulthan有趣的是,不仅仅是程序员(他们习惯了终端窗口并使用终端编辑器)。在排版中,就可读性而言,一般认为72-80个字符是一列文本的理想宽度。(因此,为什么TeX及其衍生物默认为某些人认为奇怪的窄列。)
JAB 2016年

1
@JAB我现在真的知道了。我也知道阅读合理的文本和阅读源代码是两个非常不同的事物,几乎没有共同之处,因此理想宽度无关紧要。
苏珊(Sulthan)2016年

1
“另一个原因是函数名称总是始于第一列,因此更容易找到。” 这不仅仅是视觉上的好处:现在我们可以搜索正则表达式,^start_of_a_long_func并立即使用我们要搜索的功能。
underscore_d

7

这几乎是我发现的唯一一条实际上对可读性产生显着影响的代码格式化规则,并且几乎不需要花力气(假设您的代码编辑器不会与您展开争执)。

好的编程语言设计是使名称在声明/定义中的位置一致。基本原理很简单:您有一个不错的视觉锚(花括号或只是一个悬挂的凹痕),可用于立即查找名称的开头。扫描文件查找名称时,您不必真正解析语言。

这与格式化文档时相同:在开始新的部分时,您将名称以粗体显示(通常在其自己的行上)以粗体显示,而不用一句话掩埋,不加区分。

早期的C具有非常简洁的签名:返回类型是可选的,并且在签名之后声明了参数类型。名称也往往很短。这减轻了偶尔使用返回类型抵消名称的影响。

double dot(x, y);

还是很容易消化的。

C ++使这一点变得更糟。它将参数类型规范移至签名中,从而使签名更长。后来在C的标准化过程中采用了这种语法。

static struct origin *find_origin(struct scoreboard *sb,
                  struct commit *parent,
                  struct origin *origin)

较不易消化,但还不错。(摘自Git)

现在考虑使用长的,描述性的名称和参数化的类型的现代编程实践,并了解这种选择是如何造成灾难性的。Boost标头中的示例:

template <class A1, class A2, class A3, class A4, class A5, class A6>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
{ 
   typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
   return result_type(); 
}

如果您正在编写通用代码,则此类签名甚至都不会与众不同。您可以找到比这更糟糕的情况的例子,而不必太努力。

C,C ++及其派生Java和C#似乎是具有可读的声明/定义的例外。他们流行的前辈和同行(Fortran,ALGOL,Pascal)将名称放在结果类型之前,而且值得庆幸的是,他们的许多继任者(Go,Scala,TypeScript和Swift等)也选择了更具可读性的语法。


1
值得庆幸的是,您不必编写Fortran程序。我告诉你,一旦您被迫执行函数参数,分别声明函数参数将很快引起您的注意。尤其是在尝试读取函数签名以了解期望的参数时:C ++将类型正确放置在它们所属的位置,Fortran强制您启动视觉关键字搜索以查找变量名称以确定其类型。
cmaster-恢复莫妮卡

2
将类型放入C ++真正发明的函数声明中吗?我从来没有听说过这种情况,并且一直在努力寻找引用。
underscore_d

1
请参见C语言的发展。在“标准化”部分,Ritchie提到了该语法是从C ++借用的。
user2313838 '16

5

我大约在19年与C&C ++合作时就遇到了这种风格。对于某人如何发明这种邪恶的东西感到困惑。

我能找到的唯一(潜在的)积极点是,您可以使用grep ^ FuncName找到函子定义。在十年前的某些真正的工具讨厌社区中,它可能是相关因素。在我所看到的地方,它被应用于C ++和类成员函数,甚至杀死了该属性。

猜猜我的意见。:)


1
grep -P '^(\w+::)?FuncName'
凯尔·斯特兰德

是的,函数名称中的类类型根本不妨碍使用它。因此,对于快速浏览源文件仍然是有用的。至于它看起来邪恶还是其他,意见就是意见:我开始认为它看起来更好。
underscore_d
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.