在 if 语句中分配 fopen 的结果

Posted

技术标签:

【中文标题】在 if 语句中分配 fopen 的结果【英文标题】:Assigning the result of fopen inside an if statement 【发布时间】:2012-05-09 16:47:54 【问题描述】:

我目前正在学习 C,想知道以下两段代码的性能是否不同,或者只是一种风格。

查看一些来源,他们有以下代码:

...
FILE * pFile;
pFile = fopen ("myfile.txt","r");
if (pFile == NULL)
 some code 
...

虽然我的教授在他的笔记中有以下代码:

...
FILE * pFile
if ((pFile = fopen("myfile.txt","r")) == NULL)
 some code 
...

只是想知道这仅仅是不同程序员的风格偏好,还是将 return/set 行放在 if 语句中是否有好处。

【问题讨论】:

【参考方案1】:

虽然现有的答案非常好,但关于如何处理 C 语言中的某些内容是否是性能问题,我还有几点要补充。

首先,一种快速检查方法是使用gcc -O3 编译两个版本的代码,然后比较生成的.o 文件。如果它们相同,那么当然不会有任何性能差异(至少与您当前使用的编译器/版本不同)。

话虽如此,更概念化的方法是问自己 2 个问题:

    这两段代码是否为所有可能的有效输入变量值定义了完全相同的行为,还是只为您期望的输入定义了相同的行为(甚至只是相似的行为)?

    如果它们定义完全相同的行为,您认为编译器很容易看到这一点吗?

如果是这样,则“不应该”存在性能差异,因为编译器“应该”将它们编译成它认为最有效的方式来实现所描述的行为。当然有时编译器可能非常愚蠢,所以如果它真的很重要,你可能需要检查一下。

在您的情况下,两个版本的代码都定义了完全相同的行为,我认为您很难找到一个编译器以不同方式编译它们,除非可能完全禁用优化。

【讨论】:

【参考方案2】:

正如这里所说,这两个部分显然是相同的。然而,我更喜欢第一个,因为它倾向于避免赋值运算符 = 和相等运算符 == 之间的混淆。考虑一种情况,其中有一个函数 foo(arg) 返回一个 int。你会写这样的东西:

int y;

if ((y = foo(x)) == 0) 
    ... some code ...

现在,假设您将赋值运算符与相等混淆(顺便说一句,在 if 表达式中很常见):

int y;

if ((y == foo(x)) == 0) 
    ... some code ...

由于表达式 (y == foo(x)) 的类型是 int,因此编译器认为上述是合法的 C 代码。这显然会在您的代码中产生错误。

现在,让我们考虑第一个选项:

int y;

y = foo(x);
if (y == 0) 
    ... some code ...

显然,现在您不太可能将赋值与相等混淆。此外,即使您确实将 y == foo(x); 作为语句编写,编译器也会发出警告。

【讨论】:

【参考方案3】:

两个程序是等价的。

有些人喜欢第一种风格,说它更易读,有些人喜欢第二种风格,说它更紧凑。

有关信息,请注意,在某些编码指南(MISRA 是其中之一)中,禁止使用第二种样式。 MISRA 禁止在if 语句的控制表达式中使用赋值运算符。

【讨论】:

【参考方案4】:

性能上没有区别,但显然第二种更好。

第一个将尝试打开文件与测试是否成功打开文件分开。

第二个使打开文件和测试成功成为一个单一操作,这正是您不仅应该编写代码的方式,而且也是您应该考虑的方式。您根本不应该将它们视为两个独立的操作。打开文件的操作是不完整的,直到/除非您检查了它是否正确打开。

将打开和测试视为两个独立的操作是懒惰的编码,会导致思维草率。不要这样做。

【讨论】:

【参考方案5】:

这两个变体是相等的。它不影响性能。但是,我认为第一个变体更好,因为它使事情更清楚。

【讨论】:

【参考方案6】:

它们是相同的,因为 (pFile = fopen("myfile.txt", "r")) 返回 pFile,但我个人更喜欢第一个,因为它更明确。

【讨论】:

【参考方案7】:

没有区别。更有经验的程序员有时会使用第二种形式,只是为了节省一行,但它们本质上是相同的。第二个更倾向于“UNIX-y”,大多数函数调用在继续之前都会检查错误(而不是成功)。

【讨论】:

第二种风格对于if (condition && (pFile = fopen("foo","r")) != NULL)这样的情况有优势。可能值得一提。 @DanielFischer,是的。需要指出的是,该行正在使用短路评估,并且只有在condition 为真时才会打开文件。

以上是关于在 if 语句中分配 fopen 的结果的主要内容,如果未能解决你的问题,请参考以下文章

在 if 语句 c# 中分配变量

编译器错误`在if语句中分配不兼容的类型`[重复]

ORACLE:在同一条语句中分配和检查

if 语句中的变量赋值

为啥在单个语句中分配动态对象的成员变量会导致 PHP 中的语法错误?

在 Python 中分配类布尔值