在if-else语句中“等于”与“不等于”运算符

时间:2022-11-24 19:55:21

When writing if-else statements in C, is there a reason why one would preferentially use the operator "equal to" over "not equal to", when both can produce the same outcome?

在C中写if-else语句时,当两者都能产生相同的结果时,是否有理由优先使用“等于”/“不等于”的运算符?

The code below provides context. Whereby, if the argument count is equal to 2, a string will be retrieved from the user. However, if any other value of arguments is obtained, an error message will appear.

下面的代码提供了上下文。因此,如果参数计数为2,则将从用户检索字符串。但是,如果获取了参数的任何其他值,就会出现错误消息。

int main(int argc, string argv[])
{
    string msg;

    if (argc == 2) 
    {
        msg = GetString();
    }
    else
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }

However, I can achieve the exact same outcome as the above by changing the condition of the if-else loop to being "not equals to", and flipping the associated actions. See below:

但是,通过将if-else循环的条件更改为“not equals to”,并翻转相关操作,我可以获得与上述结果完全相同的结果。见下文:

int main(int argc, string argv[])
{
    string msg;

    if (argc != 2) 
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }
    else
    {
        msg = GetString();
    }

Anyways, as both produce the same outcome, should one be used preferentially over the other?

无论如何,两者都产生相同的结果,是否应该优先使用另一个?

6 个解决方案

#1


12  

There is one technical reason in C++, and that is because if you have a habit of using == over !=, you won't need to overload as many operators.

在c++中有一个技术原因,那就是如果您习惯使用== = over !

This matters when you are dealing with function objects ("functors"). For example when you use a standard container class to store your own custom objects and want to have them automatically sorted. In order for the function object (for example std::equal_to) to work, your class needs to overload the == operator only. You don't have to overload == and != both.

这在处理函数对象时很重要。例如,当您使用标准容器类来存储您自己的自定义对象并希望它们自动排序时。为了让函数对象(例如std::equal_to)工作,您的类只需要重载==运算符。您不必重载==和!=。

Similarly, other function objects require that you only overload < and not all of < > == != <= >=.

类似地,其他函数对象只需要重载 <而不是所有<> = = != <= >=。


Generally, negations are not easy for the human brain to comprehend. Particularly if you have double negations. It is custom in most programming languages to write the equality check first, if the order doesn't matter technically. Most often it makes the code easier to read.

一般来说,否定是人类大脑不容易理解的。特别是如果你有双重否定。在大多数编程语言中,如果顺序在技术上无关紧要,那么应该先编写相等检查。通常,它使代码更容易阅读。

But as often with programming and coding style, there is no black or white rules. If the reason for the check is to find an error, then the most readable way to write error handling take precedence over "humans find negations harder to read".

但与编程和编码风格一样,通常没有黑白规则。如果检查的原因是查找错误,那么最可读的写错误处理方式将优先于“人类发现难以阅读的否定”。

Consider this not too well-written code:

考虑到这不是写得很好的代码:

if(input == good)
{
  if(format == expected)
  {
    do_stuff();
    return ok;
  }
  else
  {
    return error_format;
  }
}
else
{
  return error_input;
}

Imagine we need to add even more error handling to this. Quite a common case: suppose we are writing a parser or some data protocol decoder with lots of error handling. The multiple levels of nested braces soon would turn the code into a complete mess.

想象一下,我们需要为它添加更多的错误处理。很常见的情况:假设我们正在编写一个解析器或一些数据协议译码器,并进行大量错误处理。多层嵌套的大括号很快就会把代码弄得一团糟。

We can get rid of the need to have nested if statements if we change from == to !=.

如果我们从==改为!=,我们就不需要嵌套if语句。

if(input != good)
{
  return error_input;
}

if(format != expected)
{
  return error_format;
}

// if we got here then all is well
do_stuff();
return ok;

This will be much more readable and scale well if we need to add more error checks. So by changing to != we made the code more readable.

如果我们需要添加更多的错误检查,这将更易于阅读和扩展。因此,通过更改为!=,我们使代码更具可读性。

#2


12  

It's just a coding style issue. I hate nesting the main logic, I'll write it as:

这只是编码风格的问题。我讨厌把主要的逻辑嵌套起来,我把它写成:

int main(int argc, string argv[])
{
    if (argc != 2) 
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }

    string msg = GetString();
}

BTW: The signatrue of main should be int main(int argc, char *argv[]).

顺便说一句:main的签名应该是int main(int argc, char *argv[])。

#3


5  

I usually prefer "equal to", because it makes code more "readable" for a human. It makes code simplier. It would be more named a "nice coding guidline" than a "rule" as it does not impact runtime at all (it was part of my previous company's coding guidlines).

我通常更喜欢“相等”,因为它使代码对人类来说更“可读”。它使代码更简单。它更应该被命名为“良好的代码指导线”而不是“规则”,因为它根本不影响运行时(它是我之前的公司代码指导线的一部分)。

Check this:

检查:

if ( !isEmpty() )

It will take your brain a few milliseconds more to understand what the test does than if you write:

你的大脑需要几毫秒的时间才能理解测试的作用,而不是你写下:

if ( isEmpty() )

Even if it has no impact on runtime, I usually prefer "is equal" to "is not equal".

即使它对运行时没有影响,我通常更喜欢“is equal”to“is not equal”。

The same arguments goes to variables and function names. Prefer isSet attribute/method over isNotSet. Reading a piece of code like if ( !isNotSet() ) is easier than if if ( isSet() ), even if they are equivalent in the end.

变量和函数名也有相同的参数。比起isNotSet,更喜欢isSet属性/方法。读一段代码(如if (!isNotSet()))比读if (isSet())要容易,即使它们最终是等价的。

If you use code you have no control on and this one provides a member answering a negative questions, then:

如果您使用的是无法控制的代码,而这个代码提供了一个成员来回答消极的问题,那么:

if ( isNotSet() )

is definitely easier to read for a developer than:

对于开发人员来说,阅读肯定比:

if ( !isNotSet() )

#4


1  

As others have said, it's a style issue. There's no real difference.

正如其他人所说,这是一个风格问题。没有真正的差别。

One thing to keep in mind, though, is to try to be consistent. If you have one block checking if value1 == 2, try not to have the next block check value2 != 4. The only bad style is inconsistent style.

不过,有一件事要记住,那就是努力保持一致。如果您有一个block check If value1 = 2,请尝试不要使用下一个block check value2 != 4。唯一不好的风格是不一致的风格。

#5


0  

This is a program design question. As the programmer, you must decide which one will flow better for execution, maintenance, readability, and performance. Furthermore, these are two completely different statements. If want your function to call ONLY when argc is equal to 2 versus calling GetString(); whenever the number is not 2.

这是一个程序设计问题。作为程序员,您必须决定哪一个将更好地用于执行、维护、可读性和性能。此外,这是两个完全不同的表述。如果希望函数只在argc等于2时调用,而不是调用GetString();当数字不是2的时候。

#6


0  

Nowadays there's no semantic difference between the two cases, as even the more simple optimization applied by compilers could disrupt the "intended execution flow".

现在,这两种情况之间没有语义上的差异,因为即使编译器应用更简单的优化也可能破坏“预期的执行流”。

Maybe 30 to 40 years ago there could have been some difference between the two choices, when the code generation step of the C compiler was quite adherent to the written code.

也许30到40年前,当C编译器的代码生成步骤与编写的代码完全一致时,两种选择之间可能会有一些不同。

The actual difference is today in the syntax and style clarity.

真正的区别在于语法和风格的清晰。

So, while writing

所以,在写

while( *dst++=*src++ );

nowadays could generate the very same machine code as

现在可以生成与之非常相同的机器码。

for( i=0; src[i] != 0; i++ )
  dst[i] = src[i];
dst[i] = '\0';

The latter could be in general much easier to read, as seen in

一般来说,后者读起来要容易得多

if( ! isOK() )
  dontDoIt();
else
  doIt();

and in

而在

if( isOK() )
  doIt()
else
  dontDoIt();

But be assured, "clarity" is not an absolute value: it depends not just upon the "programming skills and taste" of the readers/reviewers, but also in the code itself.

但是请放心,“清晰”并不是绝对的价值:它不仅取决于读者/审阅者的“编程技能和品味”,还取决于代码本身。

Bottom line: make a choice of yours and stick with it for uniformity!

底线:做出你的选择并坚持一致!

#1


12  

There is one technical reason in C++, and that is because if you have a habit of using == over !=, you won't need to overload as many operators.

在c++中有一个技术原因,那就是如果您习惯使用== = over !

This matters when you are dealing with function objects ("functors"). For example when you use a standard container class to store your own custom objects and want to have them automatically sorted. In order for the function object (for example std::equal_to) to work, your class needs to overload the == operator only. You don't have to overload == and != both.

这在处理函数对象时很重要。例如,当您使用标准容器类来存储您自己的自定义对象并希望它们自动排序时。为了让函数对象(例如std::equal_to)工作,您的类只需要重载==运算符。您不必重载==和!=。

Similarly, other function objects require that you only overload < and not all of < > == != <= >=.

类似地,其他函数对象只需要重载 <而不是所有<> = = != <= >=。


Generally, negations are not easy for the human brain to comprehend. Particularly if you have double negations. It is custom in most programming languages to write the equality check first, if the order doesn't matter technically. Most often it makes the code easier to read.

一般来说,否定是人类大脑不容易理解的。特别是如果你有双重否定。在大多数编程语言中,如果顺序在技术上无关紧要,那么应该先编写相等检查。通常,它使代码更容易阅读。

But as often with programming and coding style, there is no black or white rules. If the reason for the check is to find an error, then the most readable way to write error handling take precedence over "humans find negations harder to read".

但与编程和编码风格一样,通常没有黑白规则。如果检查的原因是查找错误,那么最可读的写错误处理方式将优先于“人类发现难以阅读的否定”。

Consider this not too well-written code:

考虑到这不是写得很好的代码:

if(input == good)
{
  if(format == expected)
  {
    do_stuff();
    return ok;
  }
  else
  {
    return error_format;
  }
}
else
{
  return error_input;
}

Imagine we need to add even more error handling to this. Quite a common case: suppose we are writing a parser or some data protocol decoder with lots of error handling. The multiple levels of nested braces soon would turn the code into a complete mess.

想象一下,我们需要为它添加更多的错误处理。很常见的情况:假设我们正在编写一个解析器或一些数据协议译码器,并进行大量错误处理。多层嵌套的大括号很快就会把代码弄得一团糟。

We can get rid of the need to have nested if statements if we change from == to !=.

如果我们从==改为!=,我们就不需要嵌套if语句。

if(input != good)
{
  return error_input;
}

if(format != expected)
{
  return error_format;
}

// if we got here then all is well
do_stuff();
return ok;

This will be much more readable and scale well if we need to add more error checks. So by changing to != we made the code more readable.

如果我们需要添加更多的错误检查,这将更易于阅读和扩展。因此,通过更改为!=,我们使代码更具可读性。

#2


12  

It's just a coding style issue. I hate nesting the main logic, I'll write it as:

这只是编码风格的问题。我讨厌把主要的逻辑嵌套起来,我把它写成:

int main(int argc, string argv[])
{
    if (argc != 2) 
    {
        printf("ERROR: Please only enter a single key! \n");
        return 1;
    }

    string msg = GetString();
}

BTW: The signatrue of main should be int main(int argc, char *argv[]).

顺便说一句:main的签名应该是int main(int argc, char *argv[])。

#3


5  

I usually prefer "equal to", because it makes code more "readable" for a human. It makes code simplier. It would be more named a "nice coding guidline" than a "rule" as it does not impact runtime at all (it was part of my previous company's coding guidlines).

我通常更喜欢“相等”,因为它使代码对人类来说更“可读”。它使代码更简单。它更应该被命名为“良好的代码指导线”而不是“规则”,因为它根本不影响运行时(它是我之前的公司代码指导线的一部分)。

Check this:

检查:

if ( !isEmpty() )

It will take your brain a few milliseconds more to understand what the test does than if you write:

你的大脑需要几毫秒的时间才能理解测试的作用,而不是你写下:

if ( isEmpty() )

Even if it has no impact on runtime, I usually prefer "is equal" to "is not equal".

即使它对运行时没有影响,我通常更喜欢“is equal”to“is not equal”。

The same arguments goes to variables and function names. Prefer isSet attribute/method over isNotSet. Reading a piece of code like if ( !isNotSet() ) is easier than if if ( isSet() ), even if they are equivalent in the end.

变量和函数名也有相同的参数。比起isNotSet,更喜欢isSet属性/方法。读一段代码(如if (!isNotSet()))比读if (isSet())要容易,即使它们最终是等价的。

If you use code you have no control on and this one provides a member answering a negative questions, then:

如果您使用的是无法控制的代码,而这个代码提供了一个成员来回答消极的问题,那么:

if ( isNotSet() )

is definitely easier to read for a developer than:

对于开发人员来说,阅读肯定比:

if ( !isNotSet() )

#4


1  

As others have said, it's a style issue. There's no real difference.

正如其他人所说,这是一个风格问题。没有真正的差别。

One thing to keep in mind, though, is to try to be consistent. If you have one block checking if value1 == 2, try not to have the next block check value2 != 4. The only bad style is inconsistent style.

不过,有一件事要记住,那就是努力保持一致。如果您有一个block check If value1 = 2,请尝试不要使用下一个block check value2 != 4。唯一不好的风格是不一致的风格。

#5


0  

This is a program design question. As the programmer, you must decide which one will flow better for execution, maintenance, readability, and performance. Furthermore, these are two completely different statements. If want your function to call ONLY when argc is equal to 2 versus calling GetString(); whenever the number is not 2.

这是一个程序设计问题。作为程序员,您必须决定哪一个将更好地用于执行、维护、可读性和性能。此外,这是两个完全不同的表述。如果希望函数只在argc等于2时调用,而不是调用GetString();当数字不是2的时候。

#6


0  

Nowadays there's no semantic difference between the two cases, as even the more simple optimization applied by compilers could disrupt the "intended execution flow".

现在,这两种情况之间没有语义上的差异,因为即使编译器应用更简单的优化也可能破坏“预期的执行流”。

Maybe 30 to 40 years ago there could have been some difference between the two choices, when the code generation step of the C compiler was quite adherent to the written code.

也许30到40年前,当C编译器的代码生成步骤与编写的代码完全一致时,两种选择之间可能会有一些不同。

The actual difference is today in the syntax and style clarity.

真正的区别在于语法和风格的清晰。

So, while writing

所以,在写

while( *dst++=*src++ );

nowadays could generate the very same machine code as

现在可以生成与之非常相同的机器码。

for( i=0; src[i] != 0; i++ )
  dst[i] = src[i];
dst[i] = '\0';

The latter could be in general much easier to read, as seen in

一般来说,后者读起来要容易得多

if( ! isOK() )
  dontDoIt();
else
  doIt();

and in

而在

if( isOK() )
  doIt()
else
  dontDoIt();

But be assured, "clarity" is not an absolute value: it depends not just upon the "programming skills and taste" of the readers/reviewers, but also in the code itself.

但是请放心,“清晰”并不是绝对的价值:它不仅取决于读者/审阅者的“编程技能和品味”,还取决于代码本身。

Bottom line: make a choice of yours and stick with it for uniformity!

底线:做出你的选择并坚持一致!