为什么一个线性函数需要大括号?
Why do one liner functions require braces?
我们可以做到
if(condition)
doThis();
还有这个
while(condition)
doThat();
但不是这个
int giveMeFive()
return 5; // Error: expected a '{'
为什么不呢?
我知道语言语法在函数定义上需要 {
和 }
。我问的是条件语句(不需要大括号)和函数定义(需要大括号)之间区别的基本原理。
我认为问题是这个结构很难区分
int giveMeFive()
return 5;
和这个结构
int giveMeFive() //;
^^^
return 5;
那是不是程序员打错了
目前编译报错。但是,如果允许这样的函数定义怎么办?这将使程序变得不那么清晰。
事实上它可以像简化的内联函数一样使用
T function( parameter-list ) return expression;
但是在函数头和函数体之间放置一个分号
T function( parameter-list ) ; return expression;
更改了语义,使代码不清晰。
while 语句的区别在于 while 语句后的分号像这样
while( condition );
不改变构造的定义。在任何情况下都是 while 语句。
然而,相对于函数定义,情况有所不同。
如果允许的话,函数声明就没有区别了:
void a();
和一个什么都不做的函数的函数定义:
void a()
;
肯定会增加更多的问题而不是收获。
原因似乎主要是历史原因。
在 1989 年 ANSI C 标准之前,C 没有原型。 int
类型的参数可以隐式定义; int
以外的类型的参数必须在 {
.
之前明确定义
例如,在现代 C 语言中我们可以写成:
double sum(double x, double y) {
return x + y;
}
在 ANSI (K&R) C 之前我们必须写:
double sum(x, y)
double x;
double y;
{
return x + y;
}
函数体可能以局部变量声明开始:
double sum(x, y)
double x;
double y;
{
double z;
/* ... */
}
需要开头 {
来将参数定义与函数体分开,需要结尾 }
来匹配开头 {
.
(此语法在现代 C 中仍然允许,但已过时;在 C++ 中不允许。)
当原型被添加到语言中时,没有特别的理由允许在函数定义中省略 {
和 }
。
简单的答案是,这就是语言语法所要求的。 函数定义的语法是:
declaration-specifiers declarator declaration-listopt compound-statement
其中 复合语句 由 {
组成,后跟 0 个或多个声明和语句,然后是 }
。这是需要 复合语句 的 only 语法生成;还有很多其他只需要 声明 .
有趣的是,在 C 的前身语言 B (documented here) 中,函数定义的语法是:
name ( arguments ) statement
该语句通常 是一个复合语句(由{
和}
分隔的块),但并非必须如此。 B 不要求,甚至不允许参数和变量指定其类型,因此无需使用特定语法来将带括号的参数列表与函数体分开。在我能找到的最早的 C 参考资料 (this one, from 1974) 中,函数定义的语法已更改为需要复合语句,可能是为了适应添加的参数声明。
我们可以做到
if(condition)
doThis();
还有这个
while(condition)
doThat();
但不是这个
int giveMeFive()
return 5; // Error: expected a '{'
为什么不呢?
我知道语言语法在函数定义上需要 {
和 }
。我问的是条件语句(不需要大括号)和函数定义(需要大括号)之间区别的基本原理。
我认为问题是这个结构很难区分
int giveMeFive()
return 5;
和这个结构
int giveMeFive() //;
^^^
return 5;
那是不是程序员打错了
目前编译报错。但是,如果允许这样的函数定义怎么办?这将使程序变得不那么清晰。
事实上它可以像简化的内联函数一样使用
T function( parameter-list ) return expression;
但是在函数头和函数体之间放置一个分号
T function( parameter-list ) ; return expression;
更改了语义,使代码不清晰。
while 语句的区别在于 while 语句后的分号像这样
while( condition );
不改变构造的定义。在任何情况下都是 while 语句。
然而,相对于函数定义,情况有所不同。
如果允许的话,函数声明就没有区别了:
void a();
和一个什么都不做的函数的函数定义:
void a()
;
肯定会增加更多的问题而不是收获。
原因似乎主要是历史原因。
在 1989 年 ANSI C 标准之前,C 没有原型。 int
类型的参数可以隐式定义; int
以外的类型的参数必须在 {
.
例如,在现代 C 语言中我们可以写成:
double sum(double x, double y) {
return x + y;
}
在 ANSI (K&R) C 之前我们必须写:
double sum(x, y)
double x;
double y;
{
return x + y;
}
函数体可能以局部变量声明开始:
double sum(x, y)
double x;
double y;
{
double z;
/* ... */
}
需要开头 {
来将参数定义与函数体分开,需要结尾 }
来匹配开头 {
.
(此语法在现代 C 中仍然允许,但已过时;在 C++ 中不允许。)
当原型被添加到语言中时,没有特别的理由允许在函数定义中省略 {
和 }
。
简单的答案是,这就是语言语法所要求的。 函数定义的语法是:
declaration-specifiers declarator declaration-listopt compound-statement
其中 复合语句 由 {
组成,后跟 0 个或多个声明和语句,然后是 }
。这是需要 复合语句 的 only 语法生成;还有很多其他只需要 声明 .
有趣的是,在 C 的前身语言 B (documented here) 中,函数定义的语法是:
name ( arguments ) statement
该语句通常 是一个复合语句(由{
和}
分隔的块),但并非必须如此。 B 不要求,甚至不允许参数和变量指定其类型,因此无需使用特定语法来将带括号的参数列表与函数体分开。在我能找到的最早的 C 参考资料 (this one, from 1974) 中,函数定义的语法已更改为需要复合语句,可能是为了适应添加的参数声明。