【问题标题】:Brackets around 0 in "return (0);" statement in 'main' function - what are they for? [duplicate]“return (0);”中 0 左右的括号'main' 函数中的语句 - 它们有什么用? [复制]
【发布时间】:2011-03-10 12:08:52
【问题描述】:

通常自动生成的 c++“main”函数在末尾​​p>

return (0);

return (EXIT_SUCCESS);

但是为什么上面的语句中有括号呢?是不是和C语言有关?

// 编辑

我知道这是正确的,但有人把这些括号放在一个原因。什么原因?!

【问题讨论】:

  • 是的,你是对的,EXIT_SUCCESS,已更正。

标签: c++


【解决方案1】:

它们不是必需的(即使在 c 中)。我认为有些人使用它们使“返回”看起来更像一个函数调用,认为它更一致。

编辑:生成器可能出于自身原因这样做。以这种方式工作可能更安全或更容易。

【讨论】:

  • 但是,如果它在生成的代码中,那有什么意义呢?我想到了某种保护。
  • 可能生成的代码可能包含分号。然后带括号的版本会导致编译器错误,而没有括号的版本会静默失败或仅产生警告。
  • 我发现您可能指的特定代码生成器有一些我不喜欢的地方......例如在下一行打开花括号。在#defines 中,最好在表达式周围加上方括号,例如#define X(x) (x-2x) 因为它通常会在您执行 3 * X(2) 时有所帮助。我想不出有什么好的理由这样做以获得回报。
  • 很久以前我的导师大声而缓慢地对我说“return不是函数,它没有参数。”
【解决方案2】:

但是为什么上面有括号 陈述?是否与C有关 语言什么的?

没有。据我所知,C 从未要求 return 语句使用括号。甚至在第一个 ANSI C 标准之前,情况似乎就是这样。

然而,这实际上是一个非常有趣的问题,因为我已经看到这种风格在某些 C 程序员中很流行。

我认为对于为什么会出现这种风格的最有可能的猜测是因为所有其他分支语句(for、while、if、switch)都需要在表达式周围加上括号。人们可能没有意识到他们可以省略 return 语句的括号,或者意识到了这一点,但希望获得更统一的代码外观。

三元?有些人可能会发现它可以在视觉上将表达式“组合”成一个单元。

我的第二个最佳猜测是这种风格受到当时流行的其他语言的影响。但是,当时流行的程序替代方案(例如 Pascal)也不需要这种语法(Pascal 甚至没有 C 意义上的返回值,而只有输出参数),所以如果是这种情况,我不知道有什么特别的语言这种风格的起源。

[主观]我更喜欢那些需要最少多余装饰的样式,无论是命名约定还是如何格式化,或者是否在不必要的地方使用额外的括号。我发现任何这样的装饰往往是一个独特的个人喜好问题,爱上一种装饰代码的方式只是意味着有一天你将不得不以一种完全不同的方式处理(除非你严格单独工作,在这种情况下我羡慕你)。 [/主观]

【讨论】:

  • 您指出了一个很好的假设,即这可能是旧时代的遗迹。如果有人可以确认......如果这是编码风格和额外代码装饰的情况,那么为什么我们在其他任何地方都找不到这种风格(至少我)?嗯,也许这是一种遗物,某种传统?
  • @adf88 我会这么认为。返回表达式;并返回(expr);但是,将始终相同。不可能出现这样的情况,即它会评估不同的结果或在没有括号的情况下无法构建,所以这完全是一个偏好问题,今天的人们可能会选择这种风格,原因与一些老派程序员之前选择那种风格的原因相同(或者也许新程序员只是在看他们的代码并模仿它)。
  • 另一个可能与关于其他语言的第二个假设有关的影响因素可能是函数式语言,如 lisp 或其继任者。在 lisp 中,所有内容都遵循严格的格式,所有内容都写在括号内。这种统一性对某些人有很大的吸引力,但也被其他人讨厌,但喜欢它的人可能已经调整了他们的风格,以便在迁移到 C 时在他们的代码中获得更大的视觉统一感。
  • @adf88 Philipp 指出了一个我没有想到的案例,那就是一个带有分号的宏。那里 return (macro) 会给出一个编译器错误 where return macro;不会(充其量是警告)。这似乎不太可能解释这种风格的流行,但值得注意。
【解决方案3】:

这其实是对 BSD 内核源文件样式的要求。

man 9 style 说:

关键字后的空格(if、while、for、return、switch)。

return 语句中的值应该用括号括起来。

【讨论】:

  • 非常有趣。谢谢!
  • 引用一个使用该成语的装备并不能回答它是否取得任何成就的问题,而事实并非如此。他们的风格指南是否甚至费心试图证明这一点?
【解决方案4】:

由于可以将任何有效表达式传递给返回,因此可以根据需要添加这些括号。就像这样做:

int i = (0);

您可以将表达式嵌套在任意数量的括号中:

return (((((0)))));

【讨论】:

  • 你也可以这样做:return (42 - 42);
【解决方案5】:

在 c++14 中使用 decltype(auto) 来推断返回类型会发生变化。如果使用括号,则返回类型被推断为引用:

decltype(auto) foo1() {
   int n;
   return (n); // parentheses causes return type to be int&
}

decltype(auto) foo2() {
   int n;
   return n; // no parentheses causes return type to be int
}

template<typename T> struct TD;

int main()
{
  // main.cpp:19:22: error: aggregate 'TD<int&()> f1' has incomplete type and cannot be defined TD<decltype(foo1)> f1;
  TD<decltype(foo1)> f1;

  // main.cpp:20:22: error: aggregate 'TD<int()> f2' has incomplete type and cannot be defined TD<decltype(foo2)> f2;
  TD<decltype(foo2)> f2;
}

【讨论】:

    【解决方案6】:

    有一个愚蠢的原因 - 让 return 看起来更像一个函数调用。

    有一个更聪明的原因 - 如果生成了代码,代码生成器通常会通过在表达式周围加上括号来“安全行事”,这样他们就不必担心优先级泄漏。

    【讨论】:

      【解决方案7】:

      只是我的愚蠢猜测:

      #define RETURN(val) { if (val) printf("Main Exit With Error %d\n", val); return val; }
      
      int main(argc, argv)
      {
        ...
        RETURN (E_FILENOTFOUND);
      }
      

      【讨论】:

      • 问题是关于return,而不是RETURN...有人试图采用一种统一的风格,既可以使用真正的关键字,也可以使用宏替换 - 这将模糊地证明其他无用的括号 - 将使用正确的大小写。如果使用不同的情况,那么他们肯定会记住只在必要时使用括号。
      【解决方案8】:

      这些不是必需的。也许他们来自倾向于使用更多括号而不是更少括号when writing macros

      由于您提到了自动生成的代码,因此可能会发生用于生成宏的代码是通过重用生成宏的代码编写的,或者是由认为更多括号不会造成伤害但更少括号可能是致命的人编写的。

      【讨论】:

        【解决方案9】:

        我可以看到的一个原因:

        return (ERROR_SUCCESS);
        

        是它表达了ERROR_SUCCESS 是不透明的概念。我们都知道它是 0L,但我们不应该必须这样做。

        这是一个相当薄弱的理由。

        另一个原因是为了保持一致性,使用括号在美学上令人愉悦,这是另一个弱的原因。

        所以换句话说,我自己不使用它,但如果其他人使用它也不会翻转。 :)

        【讨论】:

        • “如何表达ERROR_SUCCESS 是不透明的概念?这到底是什么意思?但无论它是什么,括号都无法改变它。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        • 2021-02-12
        相关资源
        最近更新 更多