【问题标题】:Use of (void) before a function call [duplicate]在函数调用之前使用 (void) [重复]
【发布时间】:2012-12-06 22:20:45
【问题描述】:

可能重复:
casting unused return values to void

例如在函数调用前(void)的作用是什么

(void)func1();

我认为这与简单地调用func1(); 相同

因此,(void) 调用只是为了让其他程序员知道返回类型将被忽略,例如,如果 func1() 的返回类型为 int,或者编译器是否可能对函数执行一些优化?也许它背后还有另一个原因——它甚至是合法的 C++,还是它是在某些遗留代码中看到的 C 的残余。

谢谢

【问题讨论】:

  • casting unused return values to void 的可能重复项,以及许多其他问题...无论如何,我认为程序员不应该为了让 他们的 编译器满意而在代码中添加垃圾因为 they 会出现 that 编译器支持的无用和/或愚蠢的警告。关于“明确表示我们不关心表达式的结果”,好吧,这不是很明显,因为我们没有对它做任何事情吗?
  • @effeffe 这不是垃圾,这不是程序员告诉编译器闭嘴。这是一个程序员告诉代码的读者:“我知道这个函数会返回一些东西,但我不在乎”。与 func1(); 相反,这意味着“要么我知道这个函数返回了一些东西,我不在乎,要么我忘记正确处理返回类型并造成致命错误”。出于同样的原因,关于未处理返回类型的编译器警告永远不会是无用/愚蠢的。
  • @Lundin 所以你通常写(void) printf("hello");?
  • @effeffe 这是一个愚蠢的例子,因为它是一个众所周知的函数。 (void) 语法是您在处理用户定义的函数、API/库函数等时应该使用的语法。无论如何,您可能不应该在生产代码中使用 stdio.h,因此您可以决定在仅发布版本。
  • @Lundin 嗯,我不喜欢我的代码风格选择不一致,但这只是个人喜好问题。我更愿意认为人们在使用函数之前阅读文档,但是您的选择是有道理的,尽管我认为大多数人这样做/这样做是为了关闭编译器(事实上,这个问题及其重复项中的几乎每个答案都这么说)。

标签: c++ c


【解决方案1】:

如果某些函数使用属性声明,它会防止警告:“如果返回值未使用/检查则警告”

可能与Warning: ignoring return value of 'scanf', declared with attribute warn_unused_result 重复

查看 gcc 的文档:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (warn_unused_result) 了解更多详情

【讨论】:

  • 谢谢!我确实认为使用它会有更有用的理由。
  • 请注意,如果以这种方式声明了一个函数,那么可能是有充分理由的。所以你应该添加一个对返回值的检查,而不是公然忽略它。
  • @datenwolf:你最后一次查看printf的返回结果是什么时候? :-)
  • @KerrekSB 我认为他说的是用所述属性声明的函数,而不是通常用返回值声明的函数。我希望没有任何合理的标准库声明printf 带有这样的垃圾属性。
  • 即使编译器不抱怨printf(...)(void) printf(...) 之间的差异,其他工具(例如lint)也会抱怨。请注意:我不是在提倡这种做法。
【解决方案2】:

意义不大。它显式地将行转换为 void 表达式,这是一个仅用于其副作用并且其值被丢弃的表达式。所以线条

func1();

(void)func1();

会做同样的事情。如果编译器知道未使用表达式的值,则可以执行一些优化,但编译器很可能可以在有或没有显式 (void) 的情况下进行计算。

它可以用作一种文档形式,程序员试图表明他们没有使用表达式的值。

【讨论】:

【解决方案3】:

在一种情况下,强制转换为 void 会产生语义效果:如果值是逗号运算符的操作数并覆盖逗号运算符,则强制转换为 void 会抑制它:

struct S {
  int operator,(int) { return 0; }
};
std::cout << (S(), 42) << '\n';           // prints '0'
std::cout << ((void) S(), 42) << '\n';    // prints '42'

【讨论】:

  • +1(我希望我能得到更多)。在我在这篇文章中看到的所有答案中,这是一个很好的功能性理由。它实际上意味着除了“这里没什么可看的”和“闭嘴,愚蠢的编译器”之外的东西,就像其他答案似乎得到了磨练。谢谢你。
  • 我不知道 C++ 中的这个用途。 C 程序员还有另一个目的。 C 程序员这样做是为了避免诸如“未使用的返回值”之类的编译器警告。
【解决方案4】:

另一个奇怪的用途是允许将未知返回类型的函数用作与, 运算符相邻的序列运算符。即decltype( f(), g() ) 技术,你想说“f 可以用() 操作,g 也可以,我希望这种类型是g() 返回的类型”。但是,如果f() 返回的类型使得operator, 被重载,则结果将出乎意料。

所以你做decltype( void(f()), g() ),并在调用operator,之前丢弃f()的返回值,这样你就可以保证得到内置的序列运算符而不是一些未知的覆盖类型。

【讨论】:

    猜你喜欢
    • 2017-08-26
    • 2022-10-04
    • 2014-02-19
    • 2012-06-09
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    相关资源
    最近更新 更多