简体   繁体   中英

What's best practice for comparing function return to a simple data type?

In C , what is the best way to compare the return of a simple data type from a function in a conditional? For example, what is the difference between...

int x;
if(x = functReturnsInt() < 5)
...

and

if(functReturnsInt() < 5)
...

is it necessary to store the result of functReturnsInt() before making a comparison?

The condition in the if statement

if(x = functReturnsInt() < 5)

is just incorrect. It is equivalent to

if(x = ( functReturnsInt() < 5 ) )

So the best practice is to write

int x = functReturnsInt();
if ( x < 5 ) /*...*/

provided that you need further in the code the value returned from the function.

If the value returned from the function is needed only in an if statement then it is enough to write

if (  functReturnsInt() < 5 )
{
    /* ...*/
}
//...

is it necessary to store the result of functReturnsInt() before making a comparison?

No, but you might do so if you want it later.

Generally speaking, people expect assignments in if blocks to be wrapped in an extra layer of parenthesis now.

But in this case,

if(x = functReturnsInt() < 5)

is just wrong and should be written as

if((x = functReturnsInt()) < 5)

but as we just saw this is only used if the value will be used again.

Best practices are often a bit opinionated, but as you may have realized now, the construct:

if((x=foo()) < 5)

is something you should avoid in general, simply because of the fact that if you forget those parenthesis, then you have a bug that might be hard to trace. But here I might add that if you compile with -Wall -Wextra (which you should) you can get this:

foo.c:7:8: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
    7 |     if(x = foo() < 5) {
      |        ^

Moral lesson: Activate warnings and read them.

The only reason to store the result is if you want to use the result again and want to avoid calling the function again. There can be a number of reasons for this. For instance:

  • Performance
  • Readability
  • Correctness (the function call may have side effects)
  • Debugging (but I would wait with introducing the variable until I actually debug)

But only store the result if you want to use it again. And if you do, use this:

int x;

...

x = foo();
if(x > 5)

There is a case where this is not very important, even though you could arguably say that it can be a good habit to always use the safe option. And that is when you're using the return value as a boolean value. In this case, you can still get blamed for being a dilettante that does everything to compress the code, but there's no risk of messing things up with parenthesis:

if(ptr = malloc(sizeof *ptr)) {

This simply checks if ptr is a NULL pointer. It's equivalent to this, but this is error prone as explained above:

if((ptr = malloc(sizeof *ptr)) != NULL) {

It is not necessary to store the result. Just use the second example.

In terms of what you wrote you need to think about operator precedence. In the first case the order is function, comparison, assignment. So as long as the if statement results in != 0 the conditional code will execute. So you'd need to write it as if((x = functReturnsInt()) < 5) to have the behaviour you expect. So in this case your second example fits what you expect it to do.

In terms of the if, as long as whatever you do between the ( and the ) results in non zero it will execute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM